如何根据某列中的值有条件地使用`pandas.DataFrame.apply`?

时间:2017-12-23 01:14:56

标签: python pandas dataframe conditional apply

我有一个pandas DataFrame,我使用pandas.DataFrame.apply()

dict1 = {'file': ['filename2', 'filename2', 'filename3', 'filename4', 
         'filename4', 'filename3'], 'amount': [3, 4, 5, 1, 2, 1], 
         'front': [21889611, 36357723, 196312, 11, 42, 1992], 
         'back':[21973805, 36403870, 277500, 19, 120, 3210], 
         'type':['A', 'A', 'A', 'B', 'B', 'C']}

df1 = pd.DataFrame(dict1)
print(df1)

        file  amount     front      back type
0  filename2       3  21889611  21973805    A
1  filename2       4  36357723  36403870    A
2  filename3       5    196312    277500    A
3  filename4       1        11        19    B
4  filename4       2        42       120    B
5  filename3       1      1992      3210    C

我的任务是在N列和front列之间进行back随机抽取,其中N等于amount列中的值:

def my_func(x):
    return np.random.choice(np.arange(x.front, x.back+1), x.amount).tolist()

我只想在type等于A的行上应用此函数。

如果我没有条件,我会按如下方式使用pd.DataFrame.apply()

df1["new_column"] = df1.apply(my_func, axis=1)

仅在type==A时应用此功能,我可以执行类似

的操作
if set(['A']).issubset(df1['type']):
    df1["new_column"] = df1.apply(my_func, axis=1)

然而,这实际上并不起作用--- my_func适用于所有功能。

(1)为什么上述工作没有按预期进行?

(2)如何有效地仅将my_func应用于满足type==A的行?在上面的示例中,这将是前三行,接下来的三行是NA

1 个答案:

答案 0 :(得分:2)

首先过滤您的数据框,然后应用my_func。让我们使用query

df1['new_column'] = df1.query('type == "A"').apply(my_func, axis=1)

输出:

   amount      back       file     front type  \
0       3  21973805  filename2  21889611    A   
1       4  36403870  filename2  36357723    A   
2       5    277500  filename3    196312    A   
3       1        19  filename4        11    B   
4       2       120  filename4        42    B   
5       1      3210  filename3      1992    C   

                                 new_column  
0            [21921030, 21908574, 21971743]  
1  [36391053, 36371413, 36394390, 36376405]  
2  [198648, 263355, 197017, 261666, 260815]  
3                                       NaN  
4                                       NaN  
5                                       NaN