【问题标题】:Set dataframe values based on both row-dependent and column-dependent conditions根据行相关和列相关条件设置数据框值
【发布时间】:2019-06-18 12:23:22
【问题描述】:

情况

考虑一个包含以下列的数据框df

  • 一列名为amount。此列中的所有值都是 > 0 的整数或 NaN。
  • 名为property_1property_2property_3 等的多个列。这些列中的值是任意的。

一个简单的例子df 是:

import numpy as np
import pandas as pd

data = [
    [2, 7., 2., 4., 3.],
    [np.nan, 8., 3., 4., 2.],
    [3, 9., 1., 5., 6.],
    [1, 8., 2., 4., 1.],
]
columns = ['amount', 'property_1', 'property_2', 'property_3', 'property_4']
df = pd.DataFrame(data, columns=columns)

在控制台输出中如下所示:

   amount  property_1  property_2  property_3  property_4
0     2.0         7.0         2.0         4.0         3.0
1     NaN         8.0         3.0         4.0         2.0
2     3.0         9.0         1.0         5.0         6.0
3     1.0         8.0         2.0         4.0         1.0

问题

我想将df 转换为如下所示的数据框:

   amount  property_1  property_2  property_3  property_4
0     2.0         7.0         2.0         NaN         NaN
1     NaN         NaN         NaN         NaN         NaN
2     3.0         9.0         1.0         5.0         NaN
3     1.0         8.0         NaN         NaN         NaN

基本上,我想在列名的数字后缀大于amount 值或amount 值为 NaN 的所有位置设置一个 NaN 值。

我觉得必须有一种聪明的方法来通过一些矢量化数据帧操作来实现这一点。有人知道具体是怎么回事吗?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您可以使用np.subtract.outer 为您的第一个条件构造布尔掩码。第二个 null 条件通过fillna(0) 处理,因为所有正整数都大于 0。

    # extract integers from columns
    ints = df.columns[1:].str.rsplit('_', n=1).str[-1].astype(int)
    
    # perform elementwise comparison after replacing null amounts with 0
    bool_arr = np.subtract.outer(ints, df['amount'].fillna(0)).T
    
    # apply Boolean mask to selected columns
    df.iloc[:, 1:] = df.iloc[:, 1:].mask(bool_arr > 0)
    
    print(df)
    
       amount  property_1  property_2  property_3  property_4
    0     2.0         7.0         2.0         NaN         NaN
    1     NaN         NaN         NaN         NaN         NaN
    2     3.0         9.0         1.0         5.0         NaN
    3     1.0         8.0         NaN         NaN         NaN
    

    【讨论】:

    • 非常感谢!此代码非常适用于示例数据框。然而,我只是注意到,如果我在输入数据帧中多了一行,那么第二个代码行会引发 ValueError: Lengths must match to compare 错误。这是否意味着如果输入数据框的行数与“属性”列的数量不同,则代码不起作用?如果是这样,代码是否可以适应这种情况?
    • @Xukrao,抱歉,有一个错误,现已更正:)
    • 我现在从最后一行代码(带有mask 操作的代码行)得到TypeError: ufunc 'invert' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''。这有意义吗?
    • 我使用的是 Python 3.6、NumPy 1.13.1,没有看到任何错误。 np.subtract.outer,在概念上采用 2 个 1d 数组的所有组合之间的差异来给出 2d 矩阵。然后您需要通过.T 转置结果。
    • 有趣。我正在使用 python 3.7.2、numpy 1.15.4 和 pandas 0.23.4。你用的是哪个版本的熊猫?
    猜你喜欢
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多