如何删除值小于5的行? Python,熊猫

时间:2018-01-30 04:24:41

标签: python pandas

我有一个包含大量行的数据框。有时值是其中之一,对我的目的不是很有用。

如何删除第2列和第3列的值不会超过5次的所有行?

df输入

 Col1     Col2     Col3       Col4
 1        apple    tomato     banana
 1        apple    potato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        grape    tomato     banana
 1        pear     tomato     banana
 1        lemon    tomato     banana

输出

 Col1     Col2     Col3       Col4
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana

6 个答案:

答案 0 :(得分:2)

全球计数
使用stack + value_counts + replace -

v = df[['Col2', 'Col3']]
df[v.replace(v.stack().value_counts()).gt(5).all(1)]

   Col1   Col2    Col3    Col4
0     1  apple  tomato  banana
2     1  apple  tomato  banana
3     1  apple  tomato  banana
4     1  apple  tomato  banana
5     1  apple  tomato  banana

(更新)
逐列计数

在您感兴趣的列上使用apply致电pd.Series.value_counts,并按照与之前相同的方式进行过滤 -

v = df[['Col2', 'Col3']]
df[v.replace(v.apply(pd.Series.value_counts)).gt(5).all(1)]

   Col1   Col2    Col3    Col4
0     1  apple  tomato  banana
2     1  apple  tomato  banana
3     1  apple  tomato  banana
4     1  apple  tomato  banana
5     1  apple  tomato  banana

详细
使用value_counts计算数据框中的值 -

c = v.apply(pd.Series.value_counts)
c

        Col2  Col3
apple    6.0   NaN
grape    1.0   NaN
lemon    1.0   NaN
pear     1.0   NaN
potato   NaN   1.0
tomato   NaN   8.0

调用replace,将DataFrame中的值替换为其计数 -

i = v.replace(c)
i

   Col2  Col3
0     6     8
1     6     1
2     6     8
3     6     8
4     6     8
5     6     8
6     1     8
7     1     8
8     1     8

从那时起,

m = i.gt(5).all(1)

0     True
1    False
2     True
3     True
4     True
5     True
6    False
7    False
8    False
dtype: bool

使用掩码索引df

答案 1 :(得分:1)

v=df.astype(str).sum(1)
df[v.eq(v.value_counts()[v.value_counts()>=5].index.values[0])]
Out[145]: 
   Col1   Col2    Col3    Col4
0     1  apple  tomato  banana
2     1  apple  tomato  banana
3     1  apple  tomato  banana
4     1  apple  tomato  banana
5     1  apple  tomato  banana

答案 2 :(得分:0)

创建示例数据框

import pandas as pd

text = '''Col1     Col2     Col3       Col4
 1        apple    tomato     banana
 1        apple    potato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        apple    tomato     banana
 1        grape    tomato     banana
 1        pear     tomato     banana
 1        lemon    tomato     banana'''

count = 1
data = []
for line in text.split('\n'):
    if count == 1:
        headers = line.split()
    else:
        data.append(line.split())
    count += 1

df = pd.DataFrame(data = data,columns=headers)

value_counts方法生成一个dict,其中唯一的列值作为键,count作为值。这是我分配给k的这些键。

  • value_counts返回一个Pandas系列对象但它就像一个dict

这个列表理解有一个过滤'如果'如果与其关联的值不是&t; t>则忽略键的语句。 5

在这个例子中,它返回一个只有一个值的列表,但在其他情况下它可能更多。

Col2_more_than_5 = [k for k in df['Col2'].value_counts().keys() 
if df['Col2'].value_counts()[k] > 5]

Col3_more_than_5 = [k for k in df['Col3'].value_counts().keys() 
if df['Col3'].value_counts()[k] > 5]

我现在有两个包含发生的字符串/ s的列表>每列5次,现在我创建一个选择器,返回两个语句都为真的行

df[(df['Col2'].isin(Col2_more_than_5)) & (df['Col3'].isin(Col3_more_than_5))]

' isin'如果列表中有多个值

,则该方法有效

enter image description here

答案 3 :(得分:0)

转换的简便方法

counts_col2 = df.groupby("Col2")["Col2"].transform(len)
counts_col3 = df.groupby("Col3")["Col3"].transform(len)

mask = (counts_col2 > 5) & (counts_col3 > 5)

df[mask]

输出:

   Col1   Col2    Col3    Col4
0     1  apple  tomato  banana
2     1  apple  tomato  banana
3     1  apple  tomato  banana
4     1  apple  tomato  banana
5     1  apple  tomato  banana

答案 4 :(得分:0)

也可以两次使用filter

df.groupby("Col2").filter(lambda x: len(x) >= 5) \
  .groupby("Col3").filter(lambda x: len(x) >= 5)

filter的文档  说

  

返回DataFrame的副本,不包括来自组的元素   不满足func。

指定的布尔标准

答案 5 :(得分:0)

@ALollz的最快方法

def agg_size_nosort(df):
    counts_col2 = df.groupby("Col2", sort=False)["Col2"].transform('size')
    counts_col3 = df.groupby("Col3", sort=False)["Col3"].transform('size')
    mask = (counts_col2 > 5) & (counts_col3 > 5)
    return df[mask]