![](/img/trans.png)
[英]Calculate percentiles/quantiles for a timeseries with resample or groupby - pandas
[英]Pandas: resample timeseries with groupby
鑒於以下熊貓數據幀:
In [115]: times = pd.to_datetime(pd.Series(['2014-08-25 21:00:00','2014-08-25 21:04:00',
'2014-08-25 22:07:00','2014-08-25 22:09:00']))
locations = ['HK', 'LDN', 'LDN', 'LDN']
event = ['foo', 'bar', 'baz', 'qux']
df = pd.DataFrame({'Location': locations,
'Event': event}, index=times)
df
Out[115]:
Event Location
2014-08-25 21:00:00 foo HK
2014-08-25 21:04:00 bar LDN
2014-08-25 22:07:00 baz LDN
2014-08-25 22:09:00 qux LDN
我想重新采樣數據以按計數每小時聚合一次,同時按位置分組以生成如下所示的數據框:
Out[115]:
HK LDN
2014-08-25 21:00:00 1 1
2014-08-25 22:00:00 0 2
我嘗試了 resample() 和 groupby() 的各種組合,但沒有運氣。 我該怎么辦?
在我原來的帖子中,我建議使用pd.TimeGrouper
。 現在,使用pd.Grouper
而不是pd.TimeGrouper
。 語法基本相同,但TimeGrouper
現在已被棄用,取而代之的是pd.Grouper
。
此外,雖然pd.TimeGrouper
只能通過DatetimeIndex,組pd.Grouper
罐組,通過它可以通過指定datetime列key
參數。
您可以使用 pd.Grouper 按小時對 DatetimeIndex 的pd.Grouper
進行分組:
grouper = df.groupby([pd.Grouper(freq='1H'), 'Location'])
使用count
來統計每組中的事件數:
grouper['Event'].count()
# Location
# 2014-08-25 21:00:00 HK 1
# LDN 1
# 2014-08-25 22:00:00 LDN 2
# Name: Event, dtype: int64
使用unstack
將Location
索引級別移動到列級別:
grouper['Event'].count().unstack()
# Out[49]:
# Location HK LDN
# 2014-08-25 21:00:00 1 1
# 2014-08-25 22:00:00 NaN 2
然后使用fillna
將 NaN 更改為零。
把這一切放在一起,
grouper = df.groupby([pd.Grouper(freq='1H'), 'Location'])
result = grouper['Event'].count().unstack('Location').fillna(0)
產量
Location HK LDN
2014-08-25 21:00:00 1 1
2014-08-25 22:00:00 0 2
執行此操作有兩種選擇。 他們實際上可以根據您的數據給出不同的結果。 第一個選項按位置分組,在位置組內按小時分組。 第二個選項同時按位置和小時分組。
選項 1 :使用groupby + resample
grouped = df.groupby('Location').resample('H')['Event'].count()
選項 2 :將位置和日期時間groupby(pd.Grouper)
與groupby(pd.Grouper)
組合在一起
grouped = df.groupby(['Location', pd.Grouper(freq='H')])['Event'].count()
它們都將導致以下結果:
Location
HK 2014-08-25 21:00:00 1
LDN 2014-08-25 21:00:00 1
2014-08-25 22:00:00 2
Name: Event, dtype: int64
然后重塑:
grouped.unstack('Location', fill_value=0)
會輸出
Location HK LDN
2014-08-25 21:00:00 1 1
2014-08-25 22:00:00 0 2
untubu 對他的回答很到位,但我想補充一下,如果你有第三列,比如Cost
並想像上面那樣聚合它,你可以做什么。 正是通過將 unutbu 的答案和這個答案相結合,我發現了如何做到這一點,並認為我會為未來的用戶分享。
創建一個帶有Cost
列的數據幀:
In[1]:
import pandas as pd
import numpy as np
times = pd.to_datetime([
"2014-08-25 21:00:00", "2014-08-25 21:04:00",
"2014-08-25 22:07:00", "2014-08-25 22:09:00"
])
df = pd.DataFrame({
"Location": ["HK", "LDN", "LDN", "LDN"],
"Event": ["foo", "bar", "baz", "qux"],
"Cost": [20, 24, 34, 52]
}, index = times)
df
Out[1]:
Location Event Cost
2014-08-25 21:00:00 HK foo 20
2014-08-25 21:04:00 LDN bar 24
2014-08-25 22:07:00 LDN baz 34
2014-08-25 22:09:00 LDN qux 52
現在我們通過使用agg
函數進行分組,指定每列的聚合方法,例如計數、均值、總和等。
In[2]:
grp = df.groupby([pd.Grouper(freq = "1H"), "Location"]) \
.agg({"Event": np.size, "Cost": np.mean})
grp
Out[2]:
Event Cost
Location
2014-08-25 21:00:00 HK 1 20
LDN 1 24
2014-08-25 22:00:00 LDN 2 43
那么最終unstack
與填充NaN
用零而顯示為int
,因為它的漂亮。
In[3]:
grp.unstack().fillna(0).astype(int)
Out[3]:
Event Cost
Location HK LDN HK LDN
2014-08-25 21:00:00 1 1 20 24
2014-08-25 22:00:00 0 2 0 43
這可以在不使用resample
或Grouper
情況下完成,如下所示:
df.groupby([df.index.floor("1H"), "Location"]).count()
df = (df.groupby("Location")
.resample("H", on="date")
.last()
.reset_index(drop=True))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.