我在python
和pandas
工作。
让我们假设我有一个像这样的数据框:(输入):
A B C
0 2 8 6
1 5 2 5
2 3 4 9
3 5 1 1
我想对其进行处理以最终获得一个新的数据框,该数据框看起来像(预期输出):
A B C
0 2 7 NaN
1 5 1 1
2 3 3 NaN
3 5 0 NaN
要对此进行管理,请执行以下操作:
columns = ['A', 'B', 'C']
data_1 = [[2, 5, 3, 5], [8, 2, 4, 1], [6, 5, 9, 1]]
data_1 = np.array(data_1).T
df_1 = pd.DataFrame(data=data_1, columns=columns)
df_2 = df_1
df_2['B'] -= 1
df_2['C'] = np.nan
df_2
现在看起来像这样:
A B C
0 2 7 NaN
1 5 1 NaN
2 3 3 NaN
3 5 0 NaN
现在,我想使用列df_1
和df_2
作为键,在A
和B
之间进行匹配/合并。
我尝试过isin()
来做到这一点:
df_temp = df_1[df_1[['A', 'B']].isin(df_2[['A', 'B']])]
df_2.iloc[df_temp.index] = df_temp
但是它给了我与以前相同的df_2
,而没有分别匹配5 1 1
,A
和B
的公共行C
:
A B C
0 2 7 NaN
1 5 1 NaN
2 3 3 NaN
3 5 0 NaN
如何正确执行此操作?
顺便说一句,要明确一点,匹配不应该像
一样进行但这必须通过以下方式完成:
基于指定的列作为键。
我认为这就是上面代码中的isin()
无效的原因,因为它以以前的方式进行了过滤/匹配。
另一方面,.merge()
可以用后一种方式进行匹配,但是它并不能按照我想要的方式保留行的顺序,而且很难解决。
最后,请记住,对于我的实际数据框,将仅使用2列(例如15列)作为匹配的键,因此最好为较大的数据框提供简洁的内容。
PS
请在下面查看我的答案。
答案 0 :(得分:1)
某人(我不记得他的用户名)建议以下内容(我认为有效),然后他出于某种原因删除了他的帖子(??!):
df_2=df_2.set_index(['A','B'])
temp = df_1.set_index(['A','B'])
df_2.update(temp)
df_2.reset_index(inplace=True)
答案 1 :(得分:0)
这是我在apply中使用lambda函数的建议。应该可以轻松扩展到更多列进行比较(只需相应地调整cols_to_compare即可)。顺便说一句,在生成df_2时,请确保复制df_1,否则df_2中的更改也将继承到df_1。 因此,首先生成数据:
columns = ['A', 'B', 'C']
data_1 = [[2, 5, 3, 5], [8, 2, 4, 1], [6, 5, 9, 1]]
data_1 = np.array(data_1).T
df_1 = pd.DataFrame(data=data_1, columns=columns)
df_2 = df_1.copy() # Be sure to create a copy here
df_2['B'] -= 1
df_2['C'] = np.nan
现在我们“扫描” df_1
以查找感兴趣的行:
cols_to_compare = ['A', 'B']
df_2['C'] = df_2.apply(lambda x: 1 if any((df_1.loc[:, cols_to_compare].values[:]==x[cols_to_compare].values).all(1)) else np.nan, axis=1)
所要做的是检查df_1的相关列中当前行中的值是否也与此类似。 输出为:
A B C
0 2 7 NaN
1 5 1 1.0
2 3 3 NaN
3 5 0 NaN
答案 2 :(得分:-1)
您可以使用两个for循环来完成此操作:
for row in df_2.iterrows():
for row2 in df_1.iterrows():
if [row[1]['A'],row[1]['B']] == [row2[1]['A'],row2[1]['B']]:
df_2['C'].iloc[row[0]] = row2[1]['C']
答案 3 :(得分:-1)
只需修改您的下一行:
df_temp = df_1[df_1[['A', 'B']].isin(df_2[['A', 'B']])]
具有:
df_1[df_1['A'].isin(df_2['A']) & df_1['B'].isin(df_2['B'])]
效果很好!