我有2个DataFrames,我试图找到最好的方法来迭代df_a中的每一行,并查看是否有任何值与df_b中的相应行不同。如果一个值都不同,那么我想考虑这些行是不同的。
df_a = pd.DataFrame({'ID':['E1', 'E2', 'E3'],
'NAME': ['John', 'Jane', 'Steve'],
'ROLE': ['Analyst', 'Manager', 'Intern'],
'LOCATION': ['San Francisco', 'New York City', 'Houston']})
ID NAME ROLE LOCATION
0 E1 John Analyst San Francisco
1 E2 Jane Manager New York City
2 E3 Steve Intern Houston
df_b = pd.DataFrame({'ID':['E1', 'E2', 'E3'],
'NAME': ['John', 'Jane', 'Steve'],
'ROLE': ['Analyst', 'Manager', 'Analyst'],
'LOCATION': ['San Francisco', 'Chicago', 'Houston']})
ID NAME ROLE LOCATION
0 E1 John Analyst San Francisco
1 E2 Jane Manager Chicago
2 E3 Steve Analyst Houston
在上面的2个DataFrame中,我想捕捉到E2和E3已经更改的事实,因此我可以将它们作为“更新的”行传递给我。
我目前的方法是一种“蛮力”,对于大型数据集而言,非常慢。我很好奇是否存在比仅在所有行和列上进行显式迭代更有效/更优雅的方法。我应该注意,我的实际数据包含带有自由文本字段的几列,因此我不确定这是否可能是代码缓慢行为的根源。
df_updates = pd.DataFrame(columns=df_a.columns)
for ix, a_row in df_a.iterrows():
# get the matching from from df_b
b_row = df_b[df_b['ID'] == a_row['ID']].iloc[0]
for column in a_row.index:
# check the column exists in df_b
if column in b_row.index:
# check if the values are the same
if a_row[column] != b_row[column]:
# if anything is different, capture the row
df_updates = df_updates.append(a_row, ignore_index=True)
break # break from the current iteration because we already confirmed that something has changed
else:
# If the column does not exist in df_b, then it must be a new field
df_updates = df_updates.append(a_row, ignore_index=True)
break
此代码将呈现以下结果:
ID NAME ROLE LOCATION
0 E2 Jane Manager New York City
1 E3 Steve Intern Houston
答案 0 :(得分:2)
您可以使用pandas.DataFrame.merge
df_merge = df_a.merge(df_b, on=df_a.columns.tolist(), how='left',indicator=True)
df_merge[df_merge['_merge'] == 'left_only'].drop(columns=["_merge"])
ID NAME ROLE LOCATION
1 E2 Jane Manager New York City
2 E3 Steve Intern Houston
答案 1 :(得分:1)
使用.duplicated
并在名为df_b
的新数据框中过滤df_c
df_a['df_name'], df_b['df_name'] = 'df_a', 'df_b'
df_c = df_a.append(df_b)
df_c = df_c[(~df_c.duplicated(['ID', 'NAME', 'ROLE', 'LOCATION'], keep=False)) &
(df_c['df_name'] == 'df_b')].drop('df_name', axis=1)
df_c
输出:
ID NAME ROLE LOCATION
1 E2 Jane Manager Chicago
2 E3 Steve Analyst Houston
答案 2 :(得分:0)
合并df_a
和df_b
的行:
rows_a = df_a.iloc[:,1].str.cat(df_a.iloc[:,2:],sep=',')
rows_b = df_b.iloc[:,1].str.cat(df_b.iloc[:,2:],sep=',')
result = df_a.loc[rows_a != rows_b]
print(result)
ID NAME ROLE LOCATION
1 E2 Jane Manager New York City
2 E3 Steve Intern Houston
答案 3 :(得分:0)
使用pandas.DataFrame.set_index
和ne
:
df_a = df_a.set_index("ID")
df_b = df_b.set_index("ID")
print(df_a[df_a.ne(df_b).any(1)].reset_index())
输出:
ID LOCATION NAME ROLE
0 E2 New York City Jane Manager
1 E3 Houston Steve Intern
答案 4 :(得分:0)
df_b [[[xf in(df_a == df_b).values中不是x.all()]]
ID NAME ROLE LOCATION 1 E2 Jane Manager Chicago 2 E3 Steve Analyst Houston
答案 5 :(得分:0)
由于您只对df_b中的更新行感兴趣,因此最直接的方法是从df_b中选择与df_a中的相应行不同的行
由于您将“不同”定义为“至少一个字段是不同的”,因此可以通过逐行使用np.any
获得布尔掩码。
import numpy as np
df_b[np.any(df_a != df_b, axis=1)]