首页 > 解决方案 > 如何以有效的方式检查列并将特定值相应地放入另一个数据框中的另一列?

问题描述

我有两个数据框,df1并且df2. 两者具有相同的 ID。在df2中,一个 ID 位于多行中(没有一个或其中一个columnB可以具有值“a”,并且在每一行,“columnC”中有另一个值)。

df1 = pd.DataFrame({'ID': ['111.111', '222.222', '333.333','444.444], 'columnA': [np.nan,np.nan,np.nan,np.nan]}) # or columnA does not has to be defined yet
df2 = pd.DataFrame({'ID': ['111.111', '111.111','111.111', '222.222' ,'222.222', '333.333', '333.333', '444.444'],
'columnB': [np.nan,'a',np.nan,np.nan,np.nan,np.nan,np.nan,np.nan],
'columnC':['0432', '0987','5460','0955','4356','6029','7329','9006']})

看起来像:

df1                   df2
ID       columnA       ID     columnB   columnC
111.111              111.111             0432
222.222              111.111     a       0987
333.333              111.111             5460
444.444              222.222             0955
                     222.222             4356
                     333.333             6029
                     333.333             7329
                     444.444             9006

我的目标:如果columnB == 'a'或没有columnCisin(validValues),我想将值 'AA' 放在columnA其中df1一个ID条件为真的地方。

我需要一种有效的方法。

比方说validValues = {'0987', '2638', '5460', '9386'}

预期df1

ID      columnA
111.111
222.222    AA
333.333
444.444    AA

我一直在尝试以下'直到现在:

df2['temp']=df2['columnB']

tmp_df = df2.groupby('ID').temp.apply(lambda x: 'AA' if (x=='a').any() else ' ')


tmp_df=tmp_df.to_frame()

df1['columnA']=df1.merge(tmp_df, how='outer',
               left_on=df1.ID, 
               right_on=tmp_df.index).drop('key_0', axis=1)['temp']


df2['temp']=df2['columnc']
tmp_df = df2.groupby('ID').temp.apply(lambda x: 'AA' if (x.isin(validValues)).any() else ' ')
tmp_df=tmp_df.to_frame()

df1['columnA']=df1.merge(tmp_df, how='outer',
               left_on=df1.ID, 
               right_on=tmp_df.index).drop('key_0', axis=1)['temp']

一个问题是,第二次合并覆盖了第一次。解决方案很糟糕。

此外,最好删除df1 中df2.

标签: pythonpandasdataframepandas-groupbysklearn-pandas

解决方案


df2IDs = df2[(df2['columnB'] == 'a') | (df2['columnC'].isin(validValues))][ID].tolist()

df1.loc[df1['ID'].isin(df2IDs), 'columnA'] = 'a'

1)首先过滤 df2 为 columnB 是 a 或 columnC 在您的有效值中,查看 ID 列并将其保存到列表中。

2) 获取该列表,并在 df1 中查找 ID 匹配的位置,查看 columnA 并将其设置为“a”。

编辑

df2IDs = df2.groupby('ID').filter(lambda x:any(x.columnB == 'a') | all(np.logical_not(x.columnC.isin(validValues))))['ID']

df1.loc[df1['ID'].isin(df2IDs), 'columnA'] = 'a'

我误解了你的问题。每当任何成员包含“a”或所有成员的值都不是有效值时,第一个语句将返回组。


推荐阅读