使用 pandas 按组获取计数
Get counts by group using pandas
我有一个 pandas 数据框,其中包含如下所示的数据:
ID year_month_id Class
1 201612 A
2 201612 D
3 201612 B
4 201612 Other
5 201612 Other
6 201612 Other
7 201612 A
8 201612 Other
9 201612 A
1 201701 B
所以一个 ID 可以在特定月份的任何 class 下,下个月他的 class 可能会改变。
现在我想要做的是为每个 ID 获取它在特定 class 下的月数以及它所属的最新 class 下的月数。如下所示:
ID Class_A Class_B Class_D Other Latest_Class
1 2 3 4 0 B
2 12 0 0 0 D
如何在 python 中实现此目的。
有人可以帮我吗?
另外,由于真实的数据集很大,手动验证是不可能的,我怎样才能得到一个大于1的ID列表class?
您可以通过 groupby
with aggregate count
, reshape by unstack
. Last add new column with drop_duplicates
:
获取计数
df1 = df.groupby(['ID','Class'])['year_month_id'].count().unstack(fill_value=0)
df1['Latest_Class'] = df.drop_duplicates('ID', keep='last').set_index('ID')['Class']
print (df1)
Class A B D Other Latest_Class
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
您可以统计 类 人参加了 groupby
+ value_counts
+ unstack
-
g = df.groupby('ID')
i = g.Class.value_counts().unstack(fill_value=0)
要获取最后一个 Class,请使用 groupby
+ last
-
j = g.Class.last()
连接得到你的结果 -
pd.concat([i, j], 1).rename(columns={'Class': 'LastClass'})
A B D Other LastClass
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
要获取每行超过 1 个 ID 的列表,请使用 sum
+ 掩码 -
k = i.sum(axis=1)
k[k > 1]
ID
1 2
dtype: int64
我们可以使用 pivot table 和 concat 即
ndf = df.pivot_table(index=['ID'],columns=['Class'],aggfunc='count',fill_value=0)\
.xs('year_month_id', axis=1, drop_level=True)
ndf['latest'] = df.sort_values('ID').groupby('ID')['Class'].tail(1).values
Class A B D Other latest
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
当仅旋转 2 列并将 count
用作 aggfunc
时,用零填充缺失的条目(正是这种情况),值得考虑使用 pd.crosstab
:
>> new_df = pd.crosstab(df.ID, df.Class)
>> new_df
Class A B D Other
ID
1 1 1 0 0
2 0 0 1 0
3 0 1 0 0
4 0 0 0 1
5 0 0 0 1
6 0 0 0 1
7 1 0 0 0
8 0 0 0 1
9 1 0 0 0
您通过按 ID 分组并选择最后一个条目从初始数据框中获取 class 的最后一个值:
>> df.groupby('ID').Class.last()
ID
1 B
2 D
3 B
4 Other
5 Other
6 Other
7 A
8 Other
9 A
然后你可以将它们串联起来:
>> new_df = pd.concat([new_df, df.groupby('ID').Class.last()], 1)
A B D Other Class
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
并获得您想要的输出:
>> new_df = new_df.rename(columns={'Class':'LastClass'})
A B D Other LastClass
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
将所有内容放在一起作为一条线:
>> new_df = pd.concat([pd.crosstab(df.ID, df.Class),df.groupby('ID').Class.last()],1).rename(columns={'Class':'LastClass'})
>> new_df
A B D Other LastClass
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
我有一个 pandas 数据框,其中包含如下所示的数据:
ID year_month_id Class
1 201612 A
2 201612 D
3 201612 B
4 201612 Other
5 201612 Other
6 201612 Other
7 201612 A
8 201612 Other
9 201612 A
1 201701 B
所以一个 ID 可以在特定月份的任何 class 下,下个月他的 class 可能会改变。 现在我想要做的是为每个 ID 获取它在特定 class 下的月数以及它所属的最新 class 下的月数。如下所示:
ID Class_A Class_B Class_D Other Latest_Class
1 2 3 4 0 B
2 12 0 0 0 D
如何在 python 中实现此目的。 有人可以帮我吗? 另外,由于真实的数据集很大,手动验证是不可能的,我怎样才能得到一个大于1的ID列表class?
您可以通过 groupby
with aggregate count
, reshape by unstack
. Last add new column with drop_duplicates
:
df1 = df.groupby(['ID','Class'])['year_month_id'].count().unstack(fill_value=0)
df1['Latest_Class'] = df.drop_duplicates('ID', keep='last').set_index('ID')['Class']
print (df1)
Class A B D Other Latest_Class
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
您可以统计 类 人参加了 groupby
+ value_counts
+ unstack
-
g = df.groupby('ID')
i = g.Class.value_counts().unstack(fill_value=0)
要获取最后一个 Class,请使用 groupby
+ last
-
j = g.Class.last()
连接得到你的结果 -
pd.concat([i, j], 1).rename(columns={'Class': 'LastClass'})
A B D Other LastClass
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
要获取每行超过 1 个 ID 的列表,请使用 sum
+ 掩码 -
k = i.sum(axis=1)
k[k > 1]
ID
1 2
dtype: int64
我们可以使用 pivot table 和 concat 即
ndf = df.pivot_table(index=['ID'],columns=['Class'],aggfunc='count',fill_value=0)\
.xs('year_month_id', axis=1, drop_level=True)
ndf['latest'] = df.sort_values('ID').groupby('ID')['Class'].tail(1).values
Class A B D Other latest
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
当仅旋转 2 列并将 count
用作 aggfunc
时,用零填充缺失的条目(正是这种情况),值得考虑使用 pd.crosstab
:
>> new_df = pd.crosstab(df.ID, df.Class)
>> new_df
Class A B D Other
ID
1 1 1 0 0
2 0 0 1 0
3 0 1 0 0
4 0 0 0 1
5 0 0 0 1
6 0 0 0 1
7 1 0 0 0
8 0 0 0 1
9 1 0 0 0
您通过按 ID 分组并选择最后一个条目从初始数据框中获取 class 的最后一个值:
>> df.groupby('ID').Class.last()
ID
1 B
2 D
3 B
4 Other
5 Other
6 Other
7 A
8 Other
9 A
然后你可以将它们串联起来:
>> new_df = pd.concat([new_df, df.groupby('ID').Class.last()], 1)
A B D Other Class
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
并获得您想要的输出:
>> new_df = new_df.rename(columns={'Class':'LastClass'})
A B D Other LastClass
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A
将所有内容放在一起作为一条线:
>> new_df = pd.concat([pd.crosstab(df.ID, df.Class),df.groupby('ID').Class.last()],1).rename(columns={'Class':'LastClass'})
>> new_df
A B D Other LastClass
ID
1 1 1 0 0 B
2 0 0 1 0 D
3 0 1 0 0 B
4 0 0 0 1 Other
5 0 0 0 1 Other
6 0 0 0 1 Other
7 1 0 0 0 A
8 0 0 0 1 Other
9 1 0 0 0 A