熊猫:pandas groupby可以过滤原始对象吗?

时间:2016-06-21 00:40:12

标签: python pandas filter group-by

从这个问题开始为基础。

Python Pandas: remove entries based on the number of occurrences

data = pandas.DataFrame(
    {'pid' : [1,1,1,2,2,3,3,3],
     'tag' : [23,45,62,24,45,34,25,62],
     })

   #    pid  tag
   # 0    1   23
   # 1    1   45
   # 2    1   62 
   # 3    2   24
   # 4    2   45
   # 5    3   34
   # 6    3   25
   # 7    3   62

   g = data.groupby('tag')
   g.filter(lambda x: len(x) > 1) # filters out lengths > 1. 

  #     pid  tag
  #  1    1   45
  #  2    1   62
  #  4    2   45
  #  7    3   62


 #This would create a new object g: 
 g  =   g.filter(lambda x: len(x) > 1) #where g is now a dataframe. 

我想知道是否有办法过滤掉'群组'删除 它们来自原始对象g。并且,它比从过滤的groupby创建新的groupby对象更快。

2 个答案:

答案 0 :(得分:1)

只有很多方法可以解决这个问题。我的回答包括4个解决方案我相信,还有其他方法。也许其他一些答案会提供更好的方法。

解决方案#1:

data = data.groupby('tag').filter(lambda x: len(x) > 1)
   pid  tag
1   1   45
2   1   62
4   2   45
7   3   62

解决方案#2:

data['count'] = data.groupby(['tag']).transform('count')
data.loc[data['count'] == 2]
   pid  tag     count
1   1   45  2
2   1   62  2
4   2   45  2
7   3   62  2

解决方案#3:

如果您想要删除行,可以使用.index.tolist()然后使用drop()

data['count'] = data.groupby(['tag']).transform('count')
data.drop(data[data['count'] != 2].index.tolist())
   pid  tag     count
1   1   45  2
2   1   62  2
4   2   45  2
7   3   62  2

解决方案#4:

data['count'] = data.groupby(['tag']).transform('count')
g = data.groupby('count')
data.loc[g.groups[2],('tag','pid')]
   tag  pid
1   45  1
2   62  1
4   45  2
7   62  3

答案 1 :(得分:1)

有几种选择(你的选择在底部):

第一个是inplace,我尽可能快。它比你的解决方案快一点,但不是因为丢弃了行。我可以通过第二个选项获得更好的性能,但这并没有改变。

%%timeit
data = pd.DataFrame(
    {'pid' : [1,1,1,2,2,3,3,3],
     'tag' : [23,45,62,24,45,34,25,62],
     })

mask = ~data.duplicated(subset=['tag'], keep=False)
data.drop(mask[mask].index, inplace=True)
data

1000 loops, best of 3: 1.16 ms per loop
%%timeit
data = pd.DataFrame(
    {'pid' : [1,1,1,2,2,3,3,3],
     'tag' : [23,45,62,24,45,34,25,62],
     })

data = data.loc[data.duplicated(subset=['tag'], keep=False)]
data

1000 loops, best of 3: 719 µs per loop
%%timeit
data = pd.DataFrame(
    {'pid' : [1,1,1,2,2,3,3,3],
     'tag' : [23,45,62,24,45,34,25,62],
     })
g = data.groupby('tag')
g = g.filter(lambda x: len(x) > 1)
g

1000 loops, best of 3: 1.55 ms per loop