按组阈值选择或删除行

时间:2019-04-05 16:51:11

标签: python pandas

具有如下数据帧:

group1

如果我们要选择NaN个样本至少具有2个非零值的所有行,则一种可能的解决方案是将零值转换为DF.dropna,然后使用熊猫df.replace({0: np.nan}).dropna(axis=0, thresh=2, subset=group1) df Beverage G1_1 G1_2 G1_3 G2_1 G2_2 G2_3 0 Beer 11.0 6 NaN NaN NaN NaN 1 Wine 5.1 4 2 4.1 6.0 9.4 用于过滤。例如:

Whisky

以上之所以删除了group1行,是因为group1中少于两个样本的值非零。

如何应用类似的过滤器,而不是过滤零,而是应用某些特定条件,例如,>5中的至少两个样本具有值Beer? (在这种情况下,仅应打印{{1}}行)

编辑:

还有,有没有更有效的方法来实现相同目的?我问这个问题是因为我必须将过滤器应用于一个非常大的数据框。

3 个答案:

答案 0 :(得分:7)

使用DataFrame比较运算符(eq,ne,le,lt,ge,gt),然后沿行使用sum布尔值以形成掩码。

# At least 2 non-zero values
thresh = 2
m = df[group1].ne(0).sum(1).ge(thresh)
df.loc[m]
#  Beverage  G1_1  G1_2  G1_3  G2_1  G2_2  G2_3
#0     Beer  11.0     6     0   0.0   0.0   0.0
#1     Wine   5.1     4     2   4.1   6.0   9.4

# At least 2 values greater than 5
thresh = 2
m = df[group1].gt(5).sum(1).ge(thresh)
df.loc[m]
#  Beverage  G1_1  G1_2  G1_3  G2_1  G2_2  G2_3
#0     Beer  11.0     6     0   0.0   0.0   0.0

可以通过将它们与&|组合来创建更复杂的选择。例如,间隔(2,4]内的值:

df[group1].gt(2) & df[group1].le(4) 

答案 1 :(得分:3)

您还可以使用以下逻辑:

 inds = (df[group_1] > 5).sum(axis=1) >= 2
 df.loc[inds, :]

换句话说,这翻译为:

  1. 检查所有值的条件(例如> 5),然后
  2. 检查每行满足该条件的频率(.sum(axis=1)),然后
  3. 指定必须满足此条件才能保留行(>= 2)的次数

我喜欢这种方法,因为它用途广泛并且可以轻松转换为其他问题

答案 2 :(得分:0)

认为一种可能的解决方案是为df.replace生成合适的映射字典。例如:

rep_d = {k: np.nan for k in range(0, 5)}
df.replace(rep_d).dropna(axis=0, thresh=2, subset=group1)
df

  Beverage  G1_1    G1_2    G1_3    G2_1    G2_2    G2_3
0   Beer    11.0    6       NaN     NaN     NaN     NaN

但不确定此解决方案对于很大的数据帧有多有效。