我正在尝试根据多列上的某些条件替换Pandas数据框中的值。对于单列标准,可以使用字典(例如Remap values in pandas column with a dict)非常优雅地完成此操作:
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
我正在尝试将其扩展到多个列的条件(例如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'
)扩展到一个设置,其中一列中的值被基于多列的条件替换?
我想要实现的一个例子(虽然在我的实际案例中,标准的数量是 lot 更大):
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
:
TextInput
答案 0 :(得分:2)
演示:
来源DF:
In [120]: df
Out[120]:
col1 col2
0 1 10
1 1 10
2 1 20
3 1 20
4 2 10
5 2 20
6 3 30
条件&替换DF:
In [121]: cond
Out[121]:
col1 col2 repl
1 1 20 b
2 2 10 c
0 1 10 a
3 2 20 d
解决方案:
In [121]: res = df.merge(cond, how='left')
的产率:
In [122]: res
Out[122]:
col1 col2 repl
0 1 10 a
1 1 10 a
2 1 20 b
3 1 20 b
4 2 10 c
5 2 20 d
6 3 30 NaN # <-- NOTE
In [123]: res['col1'] = res.pop('repl').fillna(res['col1'])
In [124]: res
Out[124]:
col1 col2
0 a 10
1 a 10
2 b 20
3 b 20
4 c 10
5 d 20
6 3 30
答案 1 :(得分:2)
我们可以使用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"])
如果合并后的结果值为col1
,则填写NaN
的值。
答案 2 :(得分:1)
此方法可能比pandas
功能更有效,因为它依赖于numpy
数组和字典映射。
import pandas as pd
df = pd.DataFrame({'col1': {0:1, 1:1, 2:2, 3:2}, 'col2': {0:10, 1:20, 2:10, 3:20}})
rdict = {(1, 10): 'a', (1, 20): 'b', (2, 10): 'c', (2, 20): 'd'}
df['col1'] = list(map(rdict.get, [(x[0], x[1]) for x in df1[['c1', 'c2']].values]))