查找每个组的唯一项目数

时间:2017-12-19 17:42:43

标签: python pandas dataframe

我有df A看起来像,

type    number    date 
1       1         2017-10-01
2       1         2017-10-31
1       2         2017-09-01
1       2         2017-08-01
2       2         2017-06-01

首先,我想分组number并选择每个群组至少需要包含type == 1的一行和type == 2的一行的群组;为了做到这一点,我首先检查每个组的大小是否必须> 2,

g = A.groupby('number')
B = g.filter(lambda x: len(x) > 1) # df B gets the filter results on g  

但我不知道如何检查type12包含在上面获得的每个群组中。

其次,根据从步骤1中获取的组,我想在A中创建一个名为type_2_before_type_1的布尔列,如果最早True,则会为其分配date对于type 1date最早type 2的{​​{1}}次序是<每组0,否则False。由于每个组中可能有许多行type == 1和许多行type == 2(如何获得类型1的g['A'].transform('min')和第2行?)。结果df A看起来像是

type    number    date         type_2_before_type_1
1       1         2017-10-01   True
2       1         2017-10-31   True
1       2         2017-09-01   False
1       2         2017-08-01   False
2       2         2017-06-01   False

e.g。对于number == 2的群组,类型1 2017-08-01的最早日期会减去类型2 2017-06-01的最早日期,结果为61天;因此将False设置为type_2_before_type_1

2 个答案:

答案 0 :(得分:2)

对于第一部分,请使用groupby + nunique -

df.groupby('number').type.transform('nunique')

0    2
1    2
2    2
3    2
4    2
Name: type, dtype: int64

df = df[df.groupby('number').type.transform('nunique').gt(1)]

   type  number        date
0     1       1  2017-10-01
1     2       1  2017-10-31
2     1       2  2017-09-01
3     1       2  2017-08-01
4     2       2  2017-06-01

第二部分有点挑战,但您可以groupbyunstack,致电diff,然后获取面具 -

df['type_2_before_type_1'] = \
 df.groupby(['number', 'type'])\
      .first()\
      .unstack()\
      .diff(-1, axis=1)\
      .iloc[:, 0]\
      .reindex(df.number)\
      .astype(int)\
      .lt(0)\
      .values

df

   type  number       date  type_2_before_type_1
0     1       1 2017-10-01                  True
1     2       1 2017-10-31                  True
2     1       2 2017-09-01                 False
3     1       2 2017-08-01                 False
4     2       2 2017-06-01                 False

答案 1 :(得分:2)

g=df.groupby('number')
i=g.apply(lambda x : min(x['date'][x.type==1]))
j=g.apply(lambda x : min(x['date'][x.type==2]))
k=g.type.nunique()==2
df['New'] = df.number.map(~(i > j) & k)
df
Out[588]: 
   type  number       date    New
0     1       1 2017-10-01   True
1     2       1 2017-10-31   True
2     1       2 2017-09-01  False
3     1       2 2017-08-01  False
4     2       2 2017-06-01  False