在一列上使用多个条件来分配新列的值
Use multiple conditions on a column to assign values of new column
我正在尝试根据现有列中的字符串为我的数据分配 8 个标签之一。但是,使用我使用的方法出现此错误:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
我正在寻找 144 个不同的字符串,我想将它们分配给 8 个标签。
这是我的意思的一个简化示例。如果 A 是我的数据框中的现有列,我想使用根据 A 的值分配的字符串创建 B。
数据框:
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() 给我的错误。
据我了解,这是因为 pandas 的工作原理,但我不太了解。有没有更简单的方法来做到这一点?
如有任何帮助或指点,我们将不胜感激:)
在索引中使用.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
这里不需要itterrows
,bad practice被认为很慢。
方法一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
方法二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
评论中@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'])
这要快得多而且效果很好。
感谢大家的帮助! :)
你为什么不简单地创建一个函数并将其应用于列,如此简单如此 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
理想情况下,我更愿意从下到上按照复杂性的递增顺序
我正在尝试根据现有列中的字符串为我的数据分配 8 个标签之一。但是,使用我使用的方法出现此错误:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
我正在寻找 144 个不同的字符串,我想将它们分配给 8 个标签。
这是我的意思的一个简化示例。如果 A 是我的数据框中的现有列,我想使用根据 A 的值分配的字符串创建 B。
数据框:
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() 给我的错误。 据我了解,这是因为 pandas 的工作原理,但我不太了解。有没有更简单的方法来做到这一点?
如有任何帮助或指点,我们将不胜感激:)
在索引中使用.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
这里不需要itterrows
,bad practice被认为很慢。
方法一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
方法二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
评论中@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'])
这要快得多而且效果很好。
感谢大家的帮助! :)
你为什么不简单地创建一个函数并将其应用于列,如此简单如此 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
理想情况下,我更愿意从下到上按照复杂性的递增顺序