【问题标题】:Pandas apply but only for rows where a condition is metPandas 适用,但仅适用于满足条件的行
【发布时间】: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。

【问题讨论】:

    标签: python pandas dataframe apply


    【解决方案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
    

    【讨论】:

    【解决方案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'])。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-05
        • 1970-01-01
        • 2017-09-10
        • 2019-02-13
        • 2017-11-15
        • 2020-01-09
        • 1970-01-01
        相关资源
        最近更新 更多