use*_*999 16 python conditional calculated-columns pandas
我有一个像这样的pandas数据框:
portion used
0 1 1.0
1 2 0.3
2 3 0.0
3 4 0.8
Run Code Online (Sandbox Code Playgroud)
我想基于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
Run Code Online (Sandbox Code Playgroud)
alert基于创建新列used是1.0,alert应该是Full.used是0.0,alert应该是Empty.alert应该是Partial.最好的方法是什么?
Ffi*_*ydd 34
您可以定义一个函数,它返回不同的状态"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
Run Code Online (Sandbox Code Playgroud)
Pri*_*mer 31
或者你可以这样做:
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'
Run Code Online (Sandbox Code Playgroud)
它提供相同的输出,但在10000行上运行速度快约100倍:
100 loops, best of 3: 2.91 ms per loop
Run Code Online (Sandbox Code Playgroud)
然后使用申请:
%timeit df['alert'] = df.apply(alert, axis=1)
1 loops, best of 3: 287 ms per loop
Run Code Online (Sandbox Code Playgroud)
我想这个选择取决于你的数据帧有多大.
Zer*_*ero 11
使用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
Run Code Online (Sandbox Code Playgroud)
计时
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
Run Code Online (Sandbox Code Playgroud)
np.select()>2 个条件给定 >2 个条件(如 OP 的示例),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')
Run Code Online (Sandbox Code Playgroud)
或者将条件/选择定义为可维护性的字典(在进行添加/修订时更容易保持它们正确配对):
conditions = {
'Empty': df.used.eq(0),
'Full': df.used.eq(1),
}
df['alert'] = np.select(conditions.values(), conditions.keys(), default='Partial')
Run Code Online (Sandbox Code Playgroud)
np.select()非常快具有 5 种条件的计时(满、高、中、低、空):
df = pd.DataFrame({'used': np.random.randint(10 + 1, size=10)}).div(10)