Pandas 适用但仅适用于满足条件的行

Pandas apply but only for rows where a condition is met

我想使用 Pandas df.apply 但仅限于某些行

举个例子,我想做这样的事情,但我的实际问题有点复杂:

import pandas as pd
import math
z = pd.DataFrame({'a':[4.0,5.0,6.0,7.0,8.0],'b':[6.0,0,5.0,0,1.0]})
z.where(z['b'] != 0, z['a'] / z['b'].apply(lambda l: math.log(l)), 0)

在此示例中,我想要的是 'a' 中的值除以每行 'b' 中值的对数,对于 'b' 为 0 的行,我只想 return 0.

您可以只在 lambda 函数中使用 if 语句。

z['c'] = z.apply(lambda row: 0 if row['b'] in (0,1) else row['a'] / math.log(row['b']), axis=1)

我也排除了 1,因为 log(1) 为零。

输出:

   a  b         c
0  4  6  2.232443
1  5  0  0.000000
2  6  5  3.728010
3  7  0  0.000000
4  8  1  0.000000

如果输入值为 0,您可以使用带有条件 return 0 的 lambda,并跳过整个 where 子句:

z['c'] = z.apply(lambda x: math.log(x.b) if x.b > 0 else 0, axis=1)

您还必须将结果分配给新列 (z['c'])。

其他答案非常好,但我想我会添加另一种在某些情况下可以更快的方法——使用广播和掩码来实现相同的结果:

import numpy as np

mask = (z['b'] != 0)
z_valid = z[mask]

z['c'] = 0
z.loc[mask, 'c'] = z_valid['a'] / np.log(z_valid['b'])

尤其是对于非常大的数据帧,这种方法通常比基于 apply() 的解决方案更快。

希望这对您有所帮助。简单易读

df['c']=df['b'].apply(lambda x: 0 if x ==0 else math.log(x))

使用 np.where(),如果满足条件,则 a 除以 b 中值的对数,否则 returns 0:

import numpy as np
z['c'] = np.where(z['b'] != 0, z['a'] / np.log(z['b']), 0)

输出:

     a    b         c
0  4.0  6.0  2.232443
1  5.0  0.0  0.000000
2  6.0  5.0  3.728010
3  7.0  0.0  0.000000
4  8.0  1.0       inf