簡體   English   中英

Pandas:使用 groupby 重新采樣時間序列

[英]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罐組,通過它可以通過指定datetimekey參數


您可以使用 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

使用unstackLocation索引級別移動到列級別:

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

Pandas 0.21 答案: TimeGrouper 已被棄用

執行此操作有兩種選擇。 他們實際上可以根據您的數據給出不同的結果。 第一個選項按位置分組,在位置組內按小時分組。 第二個選項同時按位置和小時分組。

選項 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

這可以在不使用resampleGrouper情況下完成,如下所示:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM