根据Pandas DataFrame另一列的条件更新某一列

4
我可以帮您进行翻译。以下是您需要翻译的内容:

我对在Pandas数据框中新列添加文本标签感兴趣。以下示例可以工作,但我收到了复制警告,我不完全明白在这种情况下是否应忽略它。

数据框只包含字符或为空字符串:

In [1]: import pandas as pd

In [2]: df=pd.DataFrame({('A'):['x','','x',''], ('B'):['x','x','','']})

In [3]: df
Out[3]:
   A  B
0  x  x
1     x
2  x
3

创建一个名为“msg”的新列。
In [4]: df['msg'] = ''

In [5]: df
Out[5]:
   A  B msg
0  x  x
1     x
2  x
3

如果“A”不是空字符串,则将“msg”列设置为“红色”。
In [6]: df['msg'][df['A'] != ''] = 'red;'

In [7]: df
Out[7]:
   A  B  msg
0  x  x  red;
1     x
2  x     red;
3

根据'B'列的值连接字符串'blue'

In [8]: df['msg'][df['B'] != ''] += 'blue;'

In [9]: df
Out[9]:
   A  B       msg
0  x  x  red;blue;
1     x     blue;
2  x         red;
3

另外,我发现使用 numpy.where 可以得到所需的结果。在 Pandas 中应该如何正确地实现这个操作?

import numpy as np

df['msg'] += np.where(df['A'] != '','green;', '')

更新:2018年4月15日

经过进一步思考,在某些情况下保留原始DataFrame的数据但仍附加标签(例如此示例中的“颜色”)将非常有用。 @COLDSPEED的答案引导我进行以下更改(在此情况下将“blue;”更改为“blue:”,并保留列“B”数据以包括在标记中):

df['msg'] = (v.where(df.applymap(len) > 0, '') + 
             df.where(df[['B']].applymap(len)>0,'')).agg(''.join, axis=1)


   A  B         msg
0  x  x  red;blue:x
1     x      blue:x
2  x           red;
3

原始的 df 中的所有值都相同吗?还是可能不同? - cs95
我不确定我理解了。列可能包含各种字符或文本,但没有数字或NaN值。这回答了你的问题吗? - Robert
我想知道你的数据框中是否所有内容都是“x”,但你的回答在另一个方面非常有帮助 - 所有列的数据类型都是字符串对我下面发布的答案的工作至关重要。 - cs95
3个回答

4

如果您事先知道颜色,您可以使用DataFrame.wherestr.join进行掩码处理来完成此操作。

v = pd.DataFrame(
     np.repeat([['red;', 'blue;']], len(df), axis=0), 
     columns=df.columns, 
     index=df.index
) 
df['msg'] = v.where(df.applymap(len) > 0, '').agg(''.join, axis=1)

df
   A  B        msg
0  x  x  red;blue;
1     x      blue;
2  x          red;
3              

我明白你的意思。这可能非常有用。我的df源是一个Excel表格,我无法修改,但是有一些列我需要跳过,但“颜色”列表可能包含该列位置的空字符串。 - Robert
@Robert 的确,那是一种处理这种情况的有用方法。 - cs95
1
这是一个很好的做法。 - piRSquared

4

使用 pandas.DataFrame.dot
特别注意,我将数组的数据类型设置为object。否则,dot不会起作用。

a = np.array(['red', 'blue;'], object)

df.assign(msg=df.astype(bool).dot(a))

   A  B        msg
0  x  x  red;blue;
1     x      blue;
2  x          red;
3                 

4
您可以使用dotreplace
(df!='').dot(df.columns).replace({'A':'red;','B':'blue;'},regex=True)
Out[379]: 
0    red;blue;
1        blue;
2         red;
3             
dtype: object

#df['msg']=(df!='').dot(df.columns).replace({'A':'red;','B':'blue;'},regex=True)

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