import pandas as pd
问题说明
数据中样本年份不连续,所以想办法知道每个样本的最大连续年份,比如说下面的df中A是3年,B是5年
df = pd.DataFrame({'id': 'A', 'year': [2000, 2001, 2003, 2005, 2006, 2007]}).append(
pd.DataFrame({'id': 'B', 'year': [2001, 2003, 2004, 2005, 2006, 2007, 2009]}))
df
idyear0A20001A20012A20033A20054A20065A20070B20011B20032B20043B20054B20065B20076B2009
方法1:使用分组循环
参考 : https://www.jianshu.com/p/718eb7a83c8e
思路,通过标记前后两个年份差大于1的为1,然后记性累计加总,最后使用value_counts得到小组最多的
计算较慢,但是方便得到其他信息
%%time
for name,group in df.groupby('id'):
group['s'] = ((group['year'].shift(1).fillna(0) + 1).astype(int) != group['year']).cumsum()
print('group:{}'.format(name))
print(group['s'].value_counts())
group:A
3 3
1 2
2 1
Name: s, dtype: int64
group:B
2 5
3 1
1 1
Name: s, dtype: int64
Wall time: 1.99 s
方法2:使用agg聚合计算
使用agg,改善上一个方法计算太慢的缺陷
速度较大提升
%%time
df.groupby('id').agg(lambda x:(x.diff().fillna(0) -1 ).cumsum().value_counts().max())
Wall time: 13 ms
yearidA3B5
% % time
df_min_year = df.groupby('id').agg(lambda x: x[(x.diff().fillna(0) - 1).cumsum() == (
x.diff().fillna(0) - 1).cumsum().value_counts().nlargest(1).index[0]].values.min())
df_max_year = df.groupby('id').agg(lambda x: x[(x.diff().fillna(0) - 1).cumsum() == (
x.diff().fillna(0) - 1).cumsum().value_counts().nlargest(1).index[0]].values.max())
df_min_year.join(df_max_year, rsuffix='_max')
Wall time: 32 ms
yearyear_maxidA20052007B20032007
方法3:使用agg加numpy
咨询大佬的答案,速度更快但
%%time
df.groupby('id').agg(lambda x: np.diff(np.flatnonzero(np.diff(
np.r_[0, (x.diff().fillna(1)-1) == 0, 0])).reshape(-1, 2), axis=1).max()+1)
Wall time: 9 ms
yearidA3B5
tips:apply和agg
对于df.groupby.apply(lambda x:fun(x)中x为dataframe,即对dataframe操作
对于df.groupby.agg(lambda x:fun(x)中x为(n-1)个series,n是列数量
使用内置函数速度大于自定义函数
df['make'] = 3
df
idyearmake0A200031A200132A200333A200534A200635A200730B200131B200332B200433B200534B200635B200736B20093
df.groupby('id').agg(lambda x:print(x))
0 2000
1 2001
2 2003
3 2005
4 2006
5 2007
Name: year, dtype: int64
0 2001
1 2003
2 2004
3 2005
4 2006
5 2007
6 2009
Name: year, dtype: int64
0 3
1 3
2 3
3 3
4 3
5 3
Name: make, dtype: int64
0 3
1 3
2 3
3 3
4 3
5 3
6 3
Name: make, dtype: int64
yearmakeidANoneNoneBNoneNone
df.groupby('id').apply(lambda x:print(x))
id year make
0 A 2000 3
1 A 2001 3
2 A 2003 3
3 A 2005 3
4 A 2006 3
5 A 2007 3
id year make
0 A 2000 3
1 A 2001 3
2 A 2003 3
3 A 2005 3
4 A 2006 3
5 A 2007 3
id year make
0 B 2001 3
1 B 2003 3
2 B 2004 3
3 B 2005 3
4 B 2006 3
5 B 2007 3
6 B 2009 3
%%time
df.groupby('id').agg('sum')
Wall time: 6 ms
yearmakeidA1202218B1403521
%%time
df.groupby('id').agg(lambda x:x.sum())
Wall time: 12 ms
yearmakeidA1202218B1403521
%%time
df.groupby('id').apply(lambda x:x.sum())
Wall time: 9.01 ms
idyearmakeidAAAAAAA1202218BBBBBBBB1403521
转载请注明原文地址:https://blackberry.8miu.com/read-14654.html