我有一个像这样的pandas数据框:
portion used
0 1 1.0
1 2 0.3
2 3 0.0
3 4 0.8
我想根据used
列创建一个新列,以便df
看起来像这样:
portion used alert
0 1 1.0 Full
1 2 0.3 Partial
2 3 0.0 Empty
3 4 0.8 Partial
alert
列
used
为1.0
,则alert
应为Full
。used
为0.0
,则alert
应为Empty
。alert
应为Partial
。最好的方法是什么?
答案 0 :(得分:31)
您可以定义一个函数,它返回不同的状态“Full”,“Partial”,“Empty”等,然后使用df.apply
将函数应用于每一行。请注意,您必须传递关键字参数axis=1
以确保它将函数应用于行。
import pandas as pd
def alert(c):
if c['used'] == 1.0:
return 'Full'
elif c['used'] == 0.0:
return 'Empty'
elif 0.0 < c['used'] < 1.0:
return 'Partial'
else:
return 'Undefined'
df = pd.DataFrame(data={'portion':[1, 2, 3, 4], 'used':[1.0, 0.3, 0.0, 0.8]})
df['alert'] = df.apply(alert, axis=1)
# portion used alert
# 0 1 1.0 Full
# 1 2 0.3 Partial
# 2 3 0.0 Empty
# 3 4 0.8 Partial
答案 1 :(得分:24)
或者你可以这样做:
import pandas as pd
import numpy as np
df = pd.DataFrame(data={'portion':np.arange(10000), 'used':np.random.rand(10000)})
%%timeit
df.loc[df['used'] == 1.0, 'alert'] = 'Full'
df.loc[df['used'] == 0.0, 'alert'] = 'Empty'
df.loc[(df['used'] >0.0) & (df['used'] < 1.0), 'alert'] = 'Partial'
它提供相同的输出,但在10000行上运行速度快约100倍:
100 loops, best of 3: 2.91 ms per loop
然后使用apply:
%timeit df['alert'] = df.apply(alert, axis=1)
1 loops, best of 3: 287 ms per loop
我想这个选择取决于你的数据帧有多大。
答案 2 :(得分:6)
使用np.where
,通常很快
In [845]: df['alert'] = np.where(df.used == 1, 'Full',
np.where(df.used == 0, 'Empty', 'Partial'))
In [846]: df
Out[846]:
portion used alert
0 1 1.0 Full
1 2 0.3 Partial
2 3 0.0 Empty
3 4 0.8 Partial
<子>计时子>
In [848]: df.shape
Out[848]: (100000, 3)
In [849]: %timeit df['alert'] = np.where(df.used == 1, 'Full', np.where(df.used == 0, 'Empty', 'Partial'))
100 loops, best of 3: 6.17 ms per loop
In [850]: %%timeit
...: df.loc[df['used'] == 1.0, 'alert'] = 'Full'
...: df.loc[df['used'] == 0.0, 'alert'] = 'Empty'
...: df.loc[(df['used'] >0.0) & (df['used'] < 1.0), 'alert'] = 'Partial'
...:
10 loops, best of 3: 21.9 ms per loop
In [851]: %timeit df['alert'] = df.apply(alert, axis=1)
1 loop, best of 3: 2.79 s per loop
答案 3 :(得分:1)
使用旨在处理多个条件的 np.select()
。它比嵌套多级 np.where()
干净得多(而且速度也一样快)。
将条件/选择定义为两个列表(按元素配对)以及一个可选的默认值(“else”情况):
conditions = [
df.used.eq(0),
df.used.eq(1),
]
choices = [
'Empty',
'Full',
]
df['alert'] = np.select(conditions, choices, default='Partial')
或者将条件/选择定义为可维护性的字典(在添加/修改时更容易保持它们正确配对):
conditions = {
'Empty': df.used.eq(0),
'Full': df.used.eq(1),
}
df['alert'] = np.select(conditions.values(), conditions.keys(), default='Partial')
np.select()
非常快,但在某些情况下 df.loc[]
可能更快:
答案 4 :(得分:0)
无法发表评论所以提出一个新的答案:改进Ffisegydd的方法,你可以使用字典和dict.get()
方法使函数传入.apply()
更容易管理:
import pandas as pd
def alert(c):
mapping = {1.0: 'Full', 0.0: 'Empty'}
return mapping.get(c['used'], 'Partial')
df = pd.DataFrame(data={'portion':[1, 2, 3, 4], 'used':[1.0, 0.3, 0.0, 0.8]})
df['alert'] = df.apply(alert, axis=1)
根据用例的不同,您可能也希望在函数定义之外定义dict。
答案 5 :(得分:0)
df['TaxStatus'] = np.where(df.Public == 1, True, np.where(df.Public == 2, False))
这似乎可行,除了ValueError:x和y都不应该给出