Python 3.6+ 中基于单个值过滤多列行的更 pythonic 方式
A more pythonic way to filter rows across multiple columns based on single value in Python 3.6+
我正在寻求有关如何简化我的代码的帮助。 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)]
数据框示例:
目前,此代码执行无误,但 returns df 未按预期进行过滤。
我的期望是删除任何不包含值 >0
的行
可以尝试以下方法。
创建数据框
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
我正在寻求有关如何简化我的代码的帮助。 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)]
数据框示例:
目前,此代码执行无误,但 returns df 未按预期进行过滤。 我的期望是删除任何不包含值 >0
的行可以尝试以下方法。
创建数据框
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