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倍。