Python中基于另一个dataframe更新dataframe

3

我有一个DataFrame,称为df1,它除了“员工”列外,所有列都是正确的。还有另一个DataFrame,称为df2,其中包含正确的员工姓名,但存储在“职员”列中。我正在尝试基于各自的DataFrames中的“key_df1”和“key_df2”更新df1。需要一些帮助来解决这个问题。(请参见下面图像中的预期输出)

data1=[['NYC-URBAN','JON','$5000','yes','BANKING','AC32456'],['WDC-RURAL','XING','$4500','Yes','FINANCE','AD45678'],['LONDON-URBAN','EDWARDS','$3500','No','IT','DE43216'],
     ['SINGAPORE-URBAN','WOLF','$5000','No','SPORTS','RT45327'],['MUMBAI-RURAL','NEMBIAR','$2500','No','IT','Rs454457']]

data2=[['NYC','MIKE','BANKING','BIKING','AH56245'],['WDC','ALPHA','FINANCE','TREKKING','AD45678'],
     ['LONDON-URBAN','BETA','FINANCE','SLEEPING','DE43216'],['SINGAPORE','WOLF','SPORTS','DANCING','RT45307'],
     ['MUMBAI','NEMBIAR','IT','ZUDO','RS454453']]

List1=['City','Employee', 'Income','Travelling','Industry', 'Key_df1']
List2=['City','Staff','Industry','Hobby', 'Key_df1']

df1=pd.DataFrame(data1,columns=List1)
df2=pd.DataFrame(data2,columns=List2)

预期输出:

enter image description here

编辑(附加查询):

感谢回复。除了上述问题外,我想将“df1”的“Employee”列的值与“Travelling”列连接起来,只针对两个数据框中“Key_df1”和“Key_df2”相等的行。请参见下面的第二个预期输出。

enter image description here

3个回答

4

首先,在df1中设置索引为Key_df1,并将其保存为临时DataFrame:

wrk = df1.set_index('Key_df1')

然后使用索引设置为 Key_df2,仅使用 Staff 列,使用来自 df2 的数据更新(原地更新)其 Employee 列:

wrk.Employee.update(df2.set_index('Key_df2').Staff)

最后一个操作是将索引更改为“常规”列并将其移动到先前的位置:

result = wrk.reset_index().reindex(columns=List1)

结果如下:

              City Employee Income Travelling Industry   Key_df1
0        NYC-URBAN      JON  $5000        yes  BANKING   AC32456
1        WDC-RURAL    ALPHA  $4500        Yes  FINANCE   AD45678
2     LONDON-URBAN     BETA  $3500         No       IT   DE43216
3  SINGAPORE-URBAN     WOLF  $5000         No   SPORTS   RT45327
4     MUMBAI-RURAL  NEMBIAR  $2500         No       IT  Rs454457

根据“旅行”列的注释进行编辑

现在仅仅使用 update 是不够的,必须以另外一种方式解决任务。

从加入 df2.Staff(使用 set_index 进行正确连接)开始与 df1 连接:

result = df1.join(df2.set_index('Key_df2').Staff, on='Key_df1')

第二步(实际更新)是:
result.Employee.where(result.Staff.isna(), result.Staff + '_' + result.Travelling,
    inplace=True)

最后一步是删除Staff列(不再需要):

result.drop(columns=['Staff'], inplace=True)

最终结果是:
              City   Employee Income Travelling Industry   Key_df1
0        NYC-URBAN        JON  $5000        yes  BANKING   AC32456
1        WDC-RURAL  ALPHA_Yes  $4500        Yes  FINANCE   AD45678
2     LONDON-URBAN    BETA_No  $3500         No       IT   DE43216
3  SINGAPORE-URBAN       WOLF  $5000         No   SPORTS   RT45327
4     MUMBAI-RURAL    NEMBIAR  $2500         No       IT  Rs454457

嗨@Validi_Bo,感谢您的回复。我也在尝试将更新后的“Employee”列与“Travelling”列连接起来。您能帮忙吗? - Ussu20
我已经在问题中添加了预期输出。 - Ussu20

2
您可以使用布尔索引,例如:
mask = df1.Key_df1 == df2.Key_df1.reindex(df1.index)
df1.loc[mask, 'Employee'] = df2.Staff

输出:

              City Employee Income Travelling Industry   Key_df1
0        NYC-URBAN      JON  $5000        yes  BANKING   AC32456
1        WDC-RURAL    ALPHA  $4500        Yes  FINANCE   AD45678
2     LONDON-URBAN     BETA  $3500         No       IT   DE43216
3  SINGAPORE-URBAN     WOLF  $5000         No   SPORTS   RT45327
4     MUMBAI-RURAL  NEMBIAR  $2500         No       IT  Rs454457

不是的,我只是更喜欢这种方式。 - fsl
1
好的,谢谢回复。第一个更短,我喜欢它。 - Abhi_J
1
如果你愿意的话,可以在一行代码中完成它:df1.loc[df1.Key_df1 == df2.Key_df1, 'Employee'] = df2.Staff - fsl
1
@FelipeLanza 如果df2的行数与df1不同,则df1.Employee[mask] = df2.Staff会引发错误。是否有更通用的方法,因为我只是举了一个简单的例子。实际上,我的df2与df1的行数不同。 - Ussu20
1
只需使用另一个的索引重新索引较小的那个。我已经编辑过了。 - fsl
显示剩余2条评论

1

您还可以在numpy中使用:

import numpy as np

df1['Employee'] = np.where(df1['Key_df1'] == df2['Key_df1'], df2['Staff'], df1['Employee'])

2
没错,只要记住 isin 不同于等式检查。 - fsl
@FelipeLanza 你是对的。在这种情况下它可以工作,但是在大型数据框中使用它会有风险。我已经编辑了我的答案。 - Arkadiusz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接