【问题标题】:A more pythonic way to filter rows across multiple columns based on single value in Python 3.6+在 Python 3.6+ 中基于单个值过滤多列中的行的更 Pythonic 方式
【发布时间】:2021-06-21 13:42:43
【问题描述】:

我正在寻求有关如何简化代码的帮助。 DataFrame 的行数超过 100k,并且可以有多个列,其中包含字符串和整数的混合。这是一个例子df:

data = {
    "Area_1": [0, 100, 200, 0],
    "Area_2": [0, 0, 100, 100],
    "Area_3": [0, 0, 0, 100],
    "id": ["gene_x", "gene_y", "gene_z", "gene_i"],
}
df = pd.DataFrame(data, columns=["id", "Area_1", "Area_2", "Area_3"])

这是我认为可以简化大量有效但只能处理 3 列的代码的代码。如果所有列都包含整数 0,我现在想接受任意数量的列并过滤行。

预期输出: DataFrame 中的所有内容,但包含gene_x 的行。

当前代码:

cut=r'^Area'
blade = df.columns.str.contains(cut)
df[(df.loc[:,blade] > 0).any(axis=1)]

数据框示例:

目前,此代码执行没有错误,但返回 df 没有按预期过滤。 我的期望是删除不包含值 >0

的任何行

【问题讨论】:

  • 您能否提供示例输入和预期输出?
  • 用于示例数据框。它只会是 id = gene_x 的删除行。我提供了我的数据框的屏幕截图。此处将是不包含整数值> 0的中间行。还有40个其他列包含我想保留的字符串或其他值,但我只想将条件应用于包含“区域.. ...”。
  • 示例数据框再次更新。

标签: python pandas dataframe contains pandas-loc


【解决方案1】:

可以尝试以下方法。

创建数据框

import pandas as pd

data = {
    "Area_1": [0, 100, 200, 0],
    "Area_2": [0, 0, 100, 100],
    "Area_3": [0, 0, 0, 100],
    "id": ["gene_x", "gene_y", "gene_z", "gene_i"],
}
df = pd.DataFrame(data, columns=["id", "Area_1", "Area_2", "Area_3"])
df = df.set_index("id")
print(df)

输出:

        Area_1  Area_2  Area_3
id                            
gene_x       0       0       0
gene_y     100       0       0
gene_z     200     100       0
gene_i       0     100     100

创建一个布尔掩码,指示我们想要的行

# Subset the columns we are interested in.
df_tmp = df.filter(regex="^Area_", axis="columns")
mask = df_tmp == 0
print(mask.head())

# Collapse across columns
all_cols_zero = mask.all(axis=1)
print(all_cols_zero)

输出:

        Area_1  Area_2  Area_3
id                            
gene_x    True    True    True
gene_y   False    True    True
gene_z   False   False    True
gene_i    True   False   False

id
gene_x     True
gene_y    False
gene_z    False
gene_i    False
dtype: bool

将布尔掩码应用于我们的原始数据帧

# Keep rows where at least one column is non-zero.
# The ~ gets the inverse. So True becomes False.
df.loc[~all_cols_zero, :]

输出:

        Area_1  Area_2  Area_3
id                            
gene_y     100       0       0
gene_z     200     100       0
gene_i       0     100     100

【讨论】:

  • 有道理,我会放弃的。
  • 这不适用于我的数据框。我有不存在的测量值的 NaN 值,所以我不确定使用 df == 0 作为掩码是否有效。我打算用0替换NaN后尝试一下。
  • 当然,如果将 NaN 替换为 0 适用于您的数据,那没问题。您还可以修改掩码表达式以以某种方式包含 NaN。您也可以尝试修改pandas.Series.all()skipna 参数,我使用该参数将布尔值折叠为每行一个值。
猜你喜欢
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
相关资源
最近更新 更多