我正在尝试根据多列的特定条件替换 Pandas 数据框中的值。对于单列条件,这可以使用字典非常优雅地完成(例如 Remap values in pandas column with a dict ):
import pandas as pd
df = pd.DataFrame({'col1': {0:1, 1:1, 2:2}, 'col2': {0:10, 1:20, 2:20}})
rdict = {1:'a', 2:'b'}
df2 = df.replace({"col1": rdict})
输入df:
col1 col2
0 1 10
1 1 20
2 2 20
结果 df2:
col1 col2
0 a 10
1 a 20
2 b 20
我正在尝试将其扩展到多列的条件(例如 where col1==1, col2==10 -> replace)。对于单个条件,这可以像这样完成:
df3=df.copy()
df3.loc[((df['col1']==1)&(df['col2']==10)), 'col1'] = 'c'
结果是 df3:
col1 col2
0 c 10
1 1 20
2 2 20
我的现实生活中的问题有大量的标准,这将涉及大量的 df3.loc[((criteria1)&(criteria2)), column] = value 调用,这是使用字典作为“查找表”的替换远没有那么优雅。是否可以将优雅的解决方案 (df2 = df.replace({"col1": rdict})) 扩展到一个设置,其中一列中的值被基于多列的条件替换?
我正在尝试实现的示例(尽管在我的现实生活中,标准的数量很多):
df = pd.DataFrame({'col1': {0:1, 1:1, 2:2, 3:2}, 'col2': {0:10, 1:20, 2:10, 3:20}})
df3=df.copy()
df3.loc[((df['col1']==1)&(df['col2']==10)), 'col1'] = 'a'
df3.loc[((df['col1']==1)&(df['col2']==20)), 'col1'] = 'b'
df3.loc[((df['col1']==2)&(df['col2']==10)), 'col1'] = 'c'
df3.loc[((df['col1']==2)&(df['col2']==20)), 'col1'] = 'd'
输入df:
0 1 10
1 1 20
2 2 10
3 2 20
结果 df3:
col1 col2
0 a 10
1 b 20
2 c 10
3 d 20
请您参考如下方法:
我们可以使用merge。
假设你的 df 看起来像
df = pd.DataFrame({'col1': {0:1, 1:1, 2:2, 3:2, 4:2, 5:1}, 'col2': {0:10, 1:20, 2:10, 3:20, 4: 20, 5:10}})
col1 col2
0 1 10
1 1 20
2 2 10
3 2 20
4 2 20
5 1 10
并且您的条件替换可以表示为另一个数据框:
df_replace
col1 col2 val
0 1 10 a
1 1 20 b
2 2 10 c
3 2 20 d
(As OP (Bart) pointed out, you can save this in a csv file.)
然后就可以使用了
df = df.merge(df_replace, on=["col1", "col2"], how="left")
col1 col2 val
0 1 10 a
1 1 20 b
2 2 10 c
3 2 20 d
4 2 20 d
5 1 10 a
然后你只需要删除col1。
正如 MaxU 所指出的,可能有些行没有被替换并导致 NaN。我们可以使用像
df["val"] = df["val"].combine_first(df["col1"])
如果合并后的结果值为 NaN,则填充 col1 中的值。
