使用DataFrame.apply在Pandas中使用特定列创建新列

时间:2017-04-13 09:20:33

标签: python pandas dataframe

我有一个像这样的数据框

ID    8-Jan 15-Jan  22-Jan  29-Jan  5-Feb   12-Feb  LowerBound   UpperBound  Problem
001    618    720    645     573     503     447     401.329      662.670     False
002    62     80      67      94      81      65     45.710       126.289     False   
003    32     10      23      26      26      31     12.314       58.114      True 
004    22     13       1      28      19      25     16.438       41.418      True
005    9       7       9      6        8       4     1.182        20.102      False

我想创建一个新列,它是一个布尔列,这样我想遍历每个ID的所有周,如果任何值位于上限和下限列之外,我将其设置为等于True,否则为False。在这种情况下,上限和下限值是虚拟的,因此数据不会返回这些值。生成的列应与Problem

类似

我知道这样做很难的方法是非常低效的

import  pandas as pd

def Problem(df):
    r = []
    for i in range(len(df)):
        res = []
        x = [df['Week1'][i], df['Week2'][i], df['Week3'][i], df['Week4'][i], df['Week5'][i]]
        for j in range (len(x)):
            if (df['LowerBound'][i] <= x[j] <= df['UpperBound'][i]): res.append(True)
            else: res.append(False)
        if (False in res): r.append(True)
        else: r.append(False)
    return r

df['Problem'] = Problem(df)

这将有效,但它是漫长,艰难和低效的方式。我知道有df.apply可以为我做这个,但我不明白如何将我的特定功能转换为。有人可以帮忙吗?感谢

1 个答案:

答案 0 :(得分:2)

您可以使用apply更简洁地执行此操作,并调用between来测试每行的值是否在范围内,使用~反转结果并调用{{3}测试是否有任何正值:

In [24]:
df['Problem'] = df.apply(lambda x: ~x.loc['8-Jan':'12-Feb'].between(x['LowerBound'], x['UpperBound']), axis=1).any(axis=1)
df

Out[24]:
   ID  8-Jan  15-Jan  22-Jan  29-Jan  5-Feb  12-Feb  LowerBound  UpperBound  \
0   1    618     720     645     573    503     447     401.329     662.670   
1   2     62      80      67      94     81      65      45.710     126.289   
2   3     32      10      23      26     26      31      12.314      58.114   
3   4     22      13       1      28     19      25      16.438      41.418   
4   5      9       7       9       6      8       4       1.182      20.102   

  Problem  
0    True  
1   False  
2    True  
3    True  
4   False  

我们可以在这里看到各个步骤:

In [25]:
df.apply(lambda x: x.loc['8-Jan':'12-Feb'].between(x['LowerBound'], x['UpperBound']), axis=1)

Out[25]:
  8-Jan 15-Jan 22-Jan 29-Jan 5-Feb 12-Feb
0  True  False   True   True  True   True
1  True   True   True   True  True   True
2  True  False   True   True  True   True
3  True  False  False   True  True   True
4  True   True   True   True  True   True

使用~反转掩码:

In [26]:
df.apply(lambda x: ~x.loc['8-Jan':'12-Feb'].between(x['LowerBound'], x['UpperBound']), axis=1)

Out[26]:
   8-Jan 15-Jan 22-Jan 29-Jan  5-Feb 12-Feb
0  False   True  False  False  False  False
1  False  False  False  False  False  False
2  False   True  False  False  False  False
3  False   True   True  False  False  False
4  False  False  False  False  False  False

现在使用any测试是否有任何行值为正:

In [27]:
df.apply(lambda x: ~x.loc['8-Jan':'12-Feb'].between(x['LowerBound'], x['UpperBound']), axis=1).any(axis=1)

Out[27]:
0     True
1    False
2     True
3     True
4    False
dtype: bool