【问题标题】:Replacing values in specific columns in a Pandas Dataframe, when number of columns are unknown当列数未知时,替换 Pandas Dataframe 中特定列中的值
【发布时间】:2017-11-27 16:31:27
【问题描述】:

我是 Python 和堆栈交换的新手。我一直在尝试用特定列中的 np.nan 替换无效值( x12)。

我不知道我必须处理多少列,因此必须创建一个考虑到这一点的通用代码。但是我知道,前两列分别是 ID 和名称。我已经在 google 和 stacks exchange 上搜索了一个解决方案,但一直无法找到解决我的特定目标的解决方案。

我的问题是;如何替换第三列及以后的值?

我的数据框是这样的;

Data

我试过这条线:

Data[Data > 12.0] = np.nan.

这用 nan 替换了前两列

1st attempt

我试过这条线:

Data[(Data.iloc[(range(2,Columns))] >=12) & (Data.iloc[(range(2,Columns))]<=-3)] = np.nan

在哪里,

Columns = len(Data.columns)

替换第 2 行到第 6 行(列 = 7)中的所有值显然是错误的。

2nd attempt

任何想法将不胜感激。

Python 3.6.1 64 位,Qt 5.6.2,达尔文上的 PyQt5 5.6

【问题讨论】:

    标签: python-3.x pandas dataframe


    【解决方案1】:

    您正在寻找applymap() 方法。

    import pandas as pd
    import numpy as np
    
    # get the columns after the second one
    cols = Data.columns[2:]
    
    # apply mask to those columns
    new_df = Data[cols].applymap(lambda x: np.nan if x > 12 or x <= -3 else x)
    

    文档:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.applymap.html

    此方法假定您的第二列之后的列包含 floatint 值。

    【讨论】:

    • 没有必要使用iloc 来获取列名。你可以简单地使用cols= Data.columns[2:]
    • 这部分工作,它替换了无效值但切片数据帧。 “new_df”数据框仅包含值,不包含所需的 ID 和名称列。我使用pd.concat([Ids, Names, new_df], axis=1) 来合并数据框,从而得到我最初想要的结果。无论如何要替换这些值并维护原始数据框?
    【解决方案2】:

    您可以通过使用 iloc 并切片您需要的列来为数据框的特定列设置值。然后我们可以使用where设置值

    使用一些随机数据的简短示例

    df = pd.DataFrame(np.random.randint(0,10,(4,10)))
    
    
       0  1  2  3  4  5  6  7  8  9
    0  7  7  9  4  2  6  6  1  7  9
    1  0  1  2  4  5  5  3  9  0  7
    2  0  1  4  4  3  8  7  0  6  1
    3  1  4  0  2  5  7  2  7  9  9
    

    现在我们使用 iloc 设置要更新的区域和要更新的区域,并将索引为 2 的列分割到最后一列

    df.iloc[:,2:] = df.iloc[:,2:].where((df < 7) & (df > 2))
    

    这会将数据框中的值设置为NaN

       0  1    2    3    4    5    6   7    8   9
    0  7  7  NaN  4.0  NaN  6.0  6.0 NaN  NaN NaN
    1  0  1  NaN  4.0  5.0  5.0  3.0 NaN  NaN NaN
    2  0  1  4.0  4.0  3.0  NaN  NaN NaN  6.0 NaN
    3  1  4  NaN  NaN  5.0  NaN  NaN NaN  NaN NaN
    

    对于您的数据,代码是这样的

    Data.iloc[:,2:] = Data.iloc[:,2:].where((Data <= 12) & (Data >= -3))
    

    运营商说明

    我在上面直接显示的设置如下所示

    -3 &lt;= Data &lt;= 12给出这些数字之间的所有内容

    如果我们使用&amp; 运算符反转这个逻辑,它看起来像这样

    -3 &gt;= Data &lt;= 12,一个数字不能同时小于 -3 和大于 12。

    所以我们使用 or 运算符来代替 |。代码现在看起来像这样......

    Data.iloc[:,2:] = Data.iloc[:,2:].where((Data >= 12) | (Data <= -3))
    

    所以有条件地检查数据

    Data &lt;= -3 or Data &gt;= 12

    【讨论】:

    • 我假设我必须用 -3 和 12 替换 7 和 2 才能达到我想要的范围。但是当我这样做时,上面的代码将所有值替换为 NaN。这显然对我不起作用,但我是 Python 新手,不一定知道我在做什么..
    • 将 7 替换为 12,将 2 替换为 -3 .. 我认为你把它倒退了。还要适当地更改运算符。对不起,我在答案中添加了一些信息
    • 成功了!但是为什么是'(Data -3)' 而不是'(Data 12)'?这让我很困惑,我正在寻找高于 12 且低于 -3 的值。此外,这是否仅在想用 NaN 替换时才有效,如果我想用 let say x 替换它们怎么办?
    • 啊!这是有道理的,我添加了一个快速解释来解释执行该逻辑操作的正确方法,您也可以将.fillna('x') 添加到该行的末尾
    • 精彩而清晰的解释!非常感谢!
    猜你喜欢
    • 2014-06-12
    • 2019-08-18
    • 2019-07-16
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2018-12-22
    相关资源
    最近更新 更多