Skip to main content
 首页 » 编程设计

python之Pandas:根据两个列值创建一个新列

2025年05月04日24mengfanrong

学习栏目比较。 如何基于两列创建新列?

我可以做两种情况水果或蔬菜。但是对于第三个条件,做不到。 :(

df 
    basket1     basket2 
0   fruit       fruit 
1   vegetable   vegetable  
2   vegetable   both 
3   fruit       both 

结果

纽德夫

    basket1    basket2    total 
0   fruit      fruit      fruit 
1   vegetable  vegetable  vegetable   
2   vegetable  both       Unknown 
3   fruit      both      fruit 

非常感谢您的帮助!

请您参考如下方法:

更新

重新审视这一点,DataFrame.apply 是缓慢的 AF。让我们看看其他一些选项,然后进行比较。

DataFrame.apply的其他选项

  1. numpy.where

当我们只有两个选项时可以应用此方法。在您的情况下,这是真的,因为当 df.a == df.b 或 df.a == 'fruit' and df 时我们返回 df.a .b == '两者'。语法是 np.where(condition, value_if_true, value_if_false)。

In [42]: df['np_where'] = np.where( 
    ...:     ((df.a == df.b) | ((df.a == 'fruit') & (df.b == 'both'))), 
    ...:     df.a, 
    ...:     'Unknown' 
    ...: ) 
  1. numpy.select

如果您有多个条件,则可以使用此选项。其语法为 np.select(condition, values, default),其中 default 是一个可选参数。

In [43]: conditions = df.a == df.b, (df.a == 'fruit') & (df.b == 'both') 
 
In [44]: choices = df['a'], df['a'] 
 
In [45]: df['np_select'] = np.select(conditions, choices, default='Unknown') 

请注意,为了演示的目的,我创建了两个条件,即使结果产生相同的结果也是如此。

比较选项

如您所见,所有三种方法都具有相同的结果。

In [47]: df 
Out[47]: 
           a          b   np_where  np_select   df_apply 
0      fruit      fruit      fruit      fruit      fruit 
1  vegetable  vegetable  vegetable  vegetable  vegetable 
2  vegetable       both    Unknown    Unknown    Unknown 
3      fruit       both      fruit      fruit      fruit 

但它们在速度方面如何比较?为了检查这一点,让我们创建一个更新、更大的 DataFrame。我们这样做是为了了解我们的选项如何处理大量数据。

In [48]: df_large = pd.DataFrame({ 
    ...:     'a': np.random.choice(['fruit', 'vegetable'], size=1_000_000), 
    ...:     'b': np.random.choice(['fruit', 'vegetable', 'both'], size=1_000_000) 
    ...: }) 
 
In [49]: %timeit df_large['np_where'] = np.where(((df_large.a == df_large.b) | ((df_large.a == 'fruit') 
    ...:  & (df_large.b == 'both'))), df_large.a, 'Unknown') 
379 ms ± 64.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 
 
In [50]: %timeit df_large['np_select'] = np.select(((df_large.a == df_large.b), ((df_large.a == 'fruit' 
    ...: ) & (df_large.b == 'both'))), (df_large.a, df_large.a), default='Unknown') 
580 ms ± 101 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 
 
In [51]: %timeit df_large['df_apply'] = df_large.apply(total, axis=1) 
40.5 s ± 6 s per loop (mean ± std. dev. of 7 runs, 1 loop each) 

哇!如您所见,DataFrame.apply 比我们的其他两个选项慢很多并且np.where 优于np.select.

结论

  • 如果只有两个选择,请使用np.where
  • 如果有多个选择,请使用np.select
  • 不要使用DataFrame.apply(尤其是对于大型数据集)!

资源


创建你自己的函数并使用DataFrame.apply

In [104]: def total(r): 
     ...:     if r.a == r.b: 
     ...:         return r.a 
     ...:     elif (r.a == 'fruit') and (r.b == 'both'): 
     ...:         return r.a 
     ...:     return 'Unknown' 
     ...: 
 
In [105]: df = pd.DataFrame({'a': ['fruit', 'vegetable', 'vegetable', 'fruit'], 'b': ['fruit', 'vegetable', 'both', 'both']}) 
 
In [106]: df 
Out[106]: 
           a          b 
0      fruit      fruit 
1  vegetable  vegetable 
2  vegetable       both 
3      fruit       both 
 
In [107]: df['total'] = df.apply(total, axis=1) 
 
In [108]: df 
Out[108]: 
           a          b      total 
0      fruit      fruit      fruit 
1  vegetable  vegetable  vegetable 
2  vegetable       both    Unknown 
3      fruit       both      fruit