Python 查找每个组的唯一项目数

Python 查找每个组的唯一项目数,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个dfa看起来像 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 type number date type_2_before_type_1 1 1

我有一个
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
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
首先,我想按编号分组,并选择每个组需要至少包含一行
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  
但我不知道如何也检查
type
1
2
是否包含在上述各组中

第二,基于从步骤1中获得的组,我想在
a
中创建一个布尔列,称为
type\u 2\u,在
之前,如果
type 1的最早
date
减去
type 2的最早
date
为每个组的
0
,则赋值为
True
,和
False
否则。因为每组中可能有许多行的
type==1
和许多行的
type==2
(如何获得
g['A'].transform('min')
,用于类型1和类型2行?)。因此,结果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
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.对于编号=2的组,类型1的最早日期
2017-08-01
减去类型2的最早日期
2017-06-01
,结果为61天;因此,将
False
设置为
type\u 2\u然后再键入\u 1

对于第一部分,使用
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

第二部分有点挑战性,但您可以
groupby
unstack
,调用
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

对于第一部分,使用
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

第二部分有点挑战性,但您可以
groupby
unstack
,调用
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

例如,在您的号码2中,如果日期是2017-09-01 2017-02-01 2017-06-01,结果会是什么?@Wen对于编号为
的组,它会将
True
设置为
type_2_,然后再键入_1
,因为
2017-02-01-2017-06-01=-120<0
,例如,在您的号码2中,如果日期是2017-09-01 2017-02-01 2017-06-01,结果会是什么?@Wen对于
number
==2的组,它会将
True
设置为
type_2_,然后再键入_1
,因为
2017-02-01-2017-06-01=-120<0
很好的组,只需要反转掩码。@cᴏʟᴅsᴘᴇᴇᴅ 啊哈,你是对的:-)我借用了你的段落名称:-)@Wen或者干脆用
(I
代替
~(I>j)
?@Wen这个解决方案有一个问题,即对于一个组,它可能没有类型1或类型2,因此运行
g.apply(lambda x:min(x['date'][x.type==1])
g.apply(da x:min(x['date'][x.type==2])
在确保每组中都有类型1和类型2之前,可能会得到
min()arg是一个空序列
错误?我应该在op中指出它,sry。很好的一个,只需要反转掩码。@cᴏʟᴅsᴘᴇᴇᴅ 啊哈,你是对的:-)我借用了你的段落名称:-)@Wen或者干脆用
(I
代替
~(I>j)
?@Wen这个解决方案有一个问题,即对于一个组,它可能没有类型1或类型2,因此运行
g.apply(lambda x:min(x['date'][x.type==1])
g.apply(da x:min(x['date'][x.type==2])
在确保每组中都有类型1和类型2之前,可能会得到
min()arg是一个空序列
错误?我应该在op,sry中指出它。