在列上使用多个条件来分配新列的值

时间:2019-07-01 12:10:47

标签: python python-3.x pandas any

我正在尝试根据现有列中的字符串为数据分配8个标签之一。但是,使用我正在使用的方法时,出现此错误:

  

ValueError:系列的真值不明确。使用a.empty,a.bool(),a.item(),a.any()或a.all()。

我正在寻找144个不同的字符串,我希望将它们分配给8个标签。

这是我的意思的简化示例。如果A是我数据框中的现有列,我想创建B,并根据A的值分配字符串。

数据框:

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high

我当前正在使用的代码如下:

for index, row in df.iterrows():
    if df['A'] == 1:
        df['Label'] = 'low'
    elif any([df['A'] == 2, df['A'] == 3, df['A'] == 4]):
        df['Label'] = 'mid'
    elif df['A'] == 5:
        df['Label'] = 'high'

我认为正是any()的使用给了我错误。 据我了解,这是由于大熊猫的工作原理引起的,但我并不是很了解。有没有更简单的方法可以做到这一点?

任何帮助或指点将不胜感激:)

4 个答案:

答案 0 :(得分:3)

这里不需要itterrows,它bad practice并被认为很慢。

方法1 pd.cut

df['B'] = pd.cut(df['A'], [0,1,4,10], labels=['low', 'mid', 'high'])

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high

方法2 np.select

conditions = [
    df['A'] == 1,
    df['A'].isin([2, 3, 4])
]

choices = ['low', 'mid']

df['B'] = np.select(conditions, choices, default='high')

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high

答案 1 :(得分:1)

为什么不简单地创建一个函数并将其应用到列上,如此简单又如此pythonic

def mapper(x):
     if x == 1:
        return 'low'
     elif x for i in [2, 3, 4]):
        return 'mid'
     elif x == 5:
        return 'high'
     else:
        return 'wtf'

df['B'] = df['A'].apply(mapper)

另一种方法是从映射字典创建数据框并进行联接,这更加直观

或者另一种方法是引用系列map function的映射功能

理想情况下,我宁愿自下而上地按顺序增加复杂性

答案 2 :(得分:0)

.loc与索引中的条件一起使用,如下所示:

import pandas as pd
from io import StringIO

df = pd.read_csv(StringIO("""
   A
0  1
1  1
2  2
3  3
4  5
5  4
6  2
7  5
"""), sep=r"\s+")

df.loc[df["A"] == 1, "B"] = "low"
df.loc[df["A"].isin((2, 3, 4)), "B"] = "mid"
df.loc[df["A"] == 5, "B"] = "high"

print(df)

输出:

   A     B
0  1   low
1  1   low
2  2   mid
3  3   mid
4  5  high
5  4   mid
6  2   mid
7  5  high

答案 3 :(得分:0)

@ anky_91中的注释中的答案已简单地解决了该问题:

l=[df.A.eq(1),df.A.isin([2,3,4]),df.A.eq(5)]
df['B']=np.select(l,['low','mid','high'])

这快得多并且效果很好。

感谢大家的帮助! :)