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

Posted

技术标签:

【中文标题】Pandas 适用,但仅适用于满足条件的行【英文标题】:Pandas apply but only for rows where a condition is met 【发布时间】:2016-02-19 14:04:54 【问题描述】:

我想使用 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的行,我只想返回0。

【问题讨论】:

【参考方案1】:

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

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() 的解决方案更快。

【讨论】:

所以这个掩码掩盖了你不想要的值。在这种情况下,您正在“选择”那些不为零的z 值。对吗? 这是一个布尔掩码,只选择非零值。你可以在这里阅读更多:jakevdp.github.io/PythonDataScienceHandbook/…【参考方案2】:

您可以只在 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

【讨论】:

我知道我在这里玩游戏迟到了,但是为什么需要指定axis = 1?它不是在语法中指定的吗?为什么axis=1而不是0? @Windstorm1981 见“轴”:pandas.pydata.org/pandas-docs/stable/generated/…【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

以上是关于Pandas 适用,但仅适用于满足条件的行的主要内容,如果未能解决你的问题,请参考以下文章

groupby取最大值对应的行

vue中的v-if指令判断某个元素满足多个条件的写法同时也适用于逻辑判断的代码中优雅的判断可用于vue的标签上

R语言dataframe计算满足筛选条件的行的个数(筛选满足条件的数据行并计数):类似于excel的countif函数

删除所有满足正则表达式条件的行

在 Pandas 中,如何创建特定频率但仅适用于特定月份的索引?

获取所有父表数据,但仅获取满足条件的子表数据