根据组过滤DataFrame行

时间:2019-09-20 07:21:00

标签: python pandas dataframe

我正在使用具有以下结构的DataFrame学习Python /熊猫:

import pandas as pd

df = pd.DataFrame({"cus_id" : ["2370", "2370", "5100", "5100", "8450", "8450", "1630", "1630", "1630"], 
                   "cus_group" : ["A", "A", "A", "B", "B", "B", "A", "A", "B"]})

print(df)

  cus_id cus_group
0   2370         A
1   2370         A
2   5100         A
3   5100         B
4   8450         B
5   8450         B
6   1630         A
7   1630         A
8   1630         B

我的目标是过滤上述DataFrame的行。具体来说,我只想保留客户属于不同组的行。这是我的尝试:

print(df.drop_duplicates(subset = ["cus_id", "cus_group"], keep = False))

  cus_id cus_group
2   5100         A
3   5100         B
8   1630         B

不幸的是,这不是我想要的确切输出。请注意,cus_id = 1630在原始DataFrame中出现3次:在A组中两次,在B组中一次。由于它属于两个不同的组(AB),因此我不想删除该客户的任何行。也就是说,我正在寻找的输出如下:

  cus_id cus_group
2   5100         A
3   5100         B
6   1630         A
7   1630         A
8   1630         B

我不确定要实现我的目标需要缺少哪些功能。任何其他帮助将不胜感激。

5 个答案:

答案 0 :(得分:1)

groupbytransform用作nunique,这样可以将唯一计数作为系列,然后仅过滤大于1的数字:

df[df.groupby('cus_id')['cus_group'].transform('nunique')>1]

  cus_id cus_group
2   5100         A
3   5100         B
6   1630         A
7   1630         A
8   1630         B

答案 1 :(得分:1)

DataFrameGroupBy.nuniqueGroupBy.transform一起用于plt.figure(figsize=(15,10)) H = ceil(sqrt(len(good_images))) W = 1+len(good_images)//ceil(sqrt(len(good_images))) print(len(good_images),H, W) for i,im in enumerate(good_images): plt.subplot(H, W, i+1,xticks=[],yticks=[]) plt.title(im.shape) plt.imshow(im, interpolation='nearest', cmap=plt.cm.gist_gray_r) ,其大小与原始DataFrame相同,因此可能用boolean indexing过滤不相等的Series行:

1

详细信息:

df = df[df.groupby('cus_id')['cus_group'].transform('nunique').ne(1)]
print (df)
  cus_id cus_group
2   5100         A
3   5100         B
6   1630         A
7   1630         A
8   1630         B

答案 2 :(得分:1)

或使用pandas.DataFrame.groupby.filter

df.groupby('cus_id').filter(lambda x: x['cus_group'].nunique()>1)

输出:

  cus_group cus_id
2         A   5100
3         B   5100
6         A   1630
7         A   1630
8         B   1630

答案 3 :(得分:1)

您只需将保留价值更改为第一。它会给您想要的结果。

import pandas as pd

df = pd.DataFrame({"cus_id" : ["2370", "2370", "5100", "5100", "8450", "8450", "1630", "1630", "1630"], 
                   "cus_group" : ["A", "A", "A", "B", "B", "B", "A", "A", "B"]})



print(df.drop_duplicates(subset = ["cus_id", "cus_group"], keep = "first"))

编辑

我很抱歉,我误解了这个问题

您可以使用group_by进行识别,然后将transform作为nunique使用以提供结果。

答案 4 :(得分:1)

它还可以与filterduplicatedany

一起使用
df.groupby('cus_id').filter(lambda x: (~x.cus_group.duplicated(keep=False)).any())

Out[510]:
  cus_id cus_group
2  5100   A
3  5100   B
6  1630   A
7  1630   A
8  1630   B