[英]Pandas - group by consecutive ranges
我有一個具有以下結構的數據幀 - 開始,結束和高度。
數據框的一些屬性:
我想以一種高度將分組為5個長度的桶的方式對數據幀進行分組,即桶是0,1-5,6-10,11-15和> 15 。
請參閱下面的代碼示例,其中我正在尋找的是group_by_bucket函數的實現。
我試着查看其他問題,但無法得到我正在尋找的確切答案。
提前致謝!
>>> d = pd.DataFrame([[1,3,5], [4,10,7], [11,17,6], [18,26, 12], [27,30, 15], [31,40,6], [41, 42, 7]], columns=['start','end', 'height'])
>>> d
start end height
0 1 3 8
1 4 10 7
2 11 17 6
3 18 26 12
4 27 30 15
5 31 40 6
6 41 42 7
>>> d_gb = group_by_bucket(d)
>>> d_gb
start end height_grouped
0 1 17 6_10
1 18 30 11_15
2 31 42 6_10
一種方法:
df = pd.DataFrame([[1,3,10], [4,10,7], [11,17,6], [18,26, 12],
[27,30, 15], [31,40,6], [41, 42, 6]], columns=['start','end', 'height'])
使用cut
制作組:
df['groups']=pd.cut(df.height,[-1,0,5,10,15,1000])
找到斷點:
df['categories']=(df.groups!=df.groups.shift()).cumsum()
然后df
是:
"""
start end height groups categories
0 1 3 10 (5, 10] 0
1 4 10 7 (5, 10] 0
2 11 17 6 (5, 10] 0
3 18 26 12 (10, 15] 1
4 27 30 15 (10, 15] 1
5 31 40 6 (5, 10] 2
6 41 42 6 (5, 10] 2
"""
定義有趣的數據:
f = {'start':['first'],'end':['last'], 'groups':['first']}
並使用groupby.agg
函數:
df.groupby('categories').agg(f)
"""
groups end start
first last first
categories
0 (5, 10] 17 1
1 (10, 15] 30 18
2 (5, 10] 42 31
"""
您可以使用cut
與groupby
通過cut
和Series
與cumsum
用於產生組和匯總agg
, first
和last
:
bins = [-1,0,1,5,10,15,100]
print bins
[-1, 0, 1, 5, 10, 15, 100]
cut_ser = pd.cut(d['height'], bins=bins)
print cut_ser
0 (5, 10]
1 (5, 10]
2 (5, 10]
3 (10, 15]
4 (10, 15]
5 (5, 10]
6 (5, 10]
Name: height, dtype: category
Categories (6, object): [(-1, 0] < (0, 1] < (1, 5] < (5, 10] < (10, 15] < (15, 100]]
print (cut_ser.shift() != cut_ser).cumsum()
0 0
1 0
2 0
3 1
4 1
5 2
6 2
Name: height, dtype: int32
print d.groupby([(cut_ser.shift() != cut_ser).cumsum(), cut_ser])
.agg({'start' : 'first','end' : 'last'})
.reset_index(level=1).reset_index(drop=True)
.rename(columns={'height':'height_grouped'})
height_grouped start end
0 (5, 10] 1 17
1 (10, 15] 18 30
2 (5, 10] 31 42
編輯:
時間 :
In [307]: %timeit a(df)
100 loops, best of 3: 5.45 ms per loop
In [308]: %timeit b(d)
The slowest run took 4.45 times longer than the fastest. This could mean that an intermediate result is being cached
100 loops, best of 3: 3.28 ms per loop
代碼 :
d = pd.DataFrame([[1,3,5], [4,10,7], [11,17,6], [18,26, 12], [27,30, 15], [31,40,6], [41, 42, 7]], columns=['start','end', 'height'])
print d
df = d.copy()
def a(df):
df['groups']=pd.cut(df.height,[-1,0,5,10,15,1000])
df['categories']=(df.groups!=df.groups.shift()).cumsum()
f = {'start':['first'],'end':['last'], 'groups':['first']}
return df.groupby('categories').agg(f)
def b(d):
bins = [-1,0,1,5,10,15,100]
cut_ser = pd.cut(d['height'], bins=bins)
return d.groupby([(cut_ser.shift() != cut_ser).cumsum(), cut_ser]).agg({'start' : 'first','end' : 'last'}).reset_index(level=1).reset_index(drop=True).rename(columns={'height':'height_grouped'})
print a(df)
print b(d)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.