熊猫取代,多列标准

时间:2018-01-27 13:04:40

标签: python pandas

我正在尝试根据多列上的某些条件替换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

3 个答案:

答案 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]))