Python 使用条件在dataframe中生成新列
我有一个熊猫数据框,看起来像这样:Python 使用条件在dataframe中生成新列,python,pandas,conditional,calculated-columns,Python,Pandas,Conditional,Calculated Columns,我有一个熊猫数据框,看起来像这样: portion used 0 1 1.0 1 2 0.3 2 3 0.0 3 4 0.8 portion used alert 0 1 1.0 Full 1 2 0.3 Partial 2 3 0.0 Empty 3 4 0.8 Partial 我想基于used列创建一个新列
portion used
0 1 1.0
1 2 0.3
2 3 0.0
3 4 0.8
portion used alert
0 1 1.0 Full
1 2 0.3 Partial
2 3 0.0 Empty
3 4 0.8 Partial
我想基于used
列创建一个新列,因此df
如下所示:
portion used
0 1 1.0
1 2 0.3
2 3 0.0
3 4 0.8
portion used alert
0 1 1.0 Full
1 2 0.3 Partial
2 3 0.0 Empty
3 4 0.8 Partial
- 根据以下内容创建新的
警报
列
- 如果
为已使用
,1.0
应为警报
完整
- 如果使用的
为
,0.0
警报应为
空
- 否则,
应为警报
部分
最好的方法是什么?您可以定义一个函数,返回不同的状态“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
将熊猫作为pd导入
def警报(c):
如果c['used']==1.0:
返回“完整”
elif c[“已使用”]==0.0:
返回“空”
elif 0.0
或者,您可以执行以下操作:
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'
然后使用apply:
%timeit df['alert'] = df.apply(alert, axis=1)
1 loops, best of 3: 287 ms per loop
我猜选择取决于您的数据帧有多大。使用
np。其中通常很快
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
时间安排
[848]中的:df.shape
Out[848]:(100000,3)
在[849]中:%timeit df['alert']=np.where(df.used==1,'Full',np.where(df.used==0,'Empty','Partial'))
100圈,最佳3圈:每圈6.17毫秒
在[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个回路,最佳3个:每个回路21.9毫秒
在[851]中:%timeit df['alert']=df.apply(alert,axis=1)
1圈,最佳3圈:每圈2.79秒
无法评论,因此提出一个新的答案:改进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
df['TaxStatus'] = np.where(df.Public == 1, True, np.where(df.Public == 2, False))
这似乎是可行的,除了ValueError:x和y中的任何一个都应该给出,或者都不应该给出可能的伟大示例的副本。为了使代码更清楚一点(并且由于您使用的是axis=1
),可以将参数c
重新命名为行
,这样很明显,您可以访问函数中该行的所有值。如果您的条件不太复杂,这应该是可以接受的答案。关于%timeit的问题:如果第一个循环执行了100次@2.91秒,是否意味着总时间为291毫秒,略长于警报功能完成1循环的287ms时间?在这种情况下,1循环在%%timeit
之后运行3行代码。timeit
程序会自动选择循环数(本例中为100),以便在某个合理的“超时”内提供更可靠的度量(即,如果运行1个循环的时间长于此“超时”,则只有1个循环,如“使用应用”的情况)。timeit
的结果应在“每1个循环”的基础上进行比较。这就是为什么会有“运行速度快100倍”的说法:一个2.91毫秒的循环比一个287毫秒的循环快100倍。