web-dev-qa-db-ja.com

パンダ:時系列をgroup byでリサンプリングします

以下の場合pandas DataFrame:

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

データをリサンプリングして、カウントごとに1時間ごとに集計しながら、場所ごとにグループ化して、次のようなデータフレームを生成します。

Out[115]:
                               HK    LDN
          2014-08-25 21:00:00  1     1
          2014-08-25 22:00:00  0     2

Resample()とgroupby()のさまざまな組み合わせを試しましたが、運はありません。これについてどうすればいいですか?

32
AshB

元の投稿で、pd.TimeGrouper。最近では、pd.Grouper の代わりに pd.TimeGrouper。構文はほぼ同じですが、TimeGrouper現在廃止されています に代わりpd.Grouper

また、pd.TimeGrouperはDatetimeIndexでのみグループ化できました、pd.Grouperは、日時でグループ化できます。これは、 keyパラメーター で指定できます。


pd.Grouper DatetimeIndex'ed DataFrameを時間でグループ化するには:

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
40
unutbu

パンダ0.21回答: TimeGrouperは非推奨になっています

これを行うには2つのオプションがあります。実際には、データに基づいて異なる結果が得られます。最初のオプションは、場所ごとに、および場所グループ内で1時間ごとにグループ化します。 2番目のオプションは、場所と時間で同時にグループ化します。

オプション1:_groupby + resample_を使用

_grouped = df.groupby('Location').resample('H')['Event'].count()
_

オプション2:ロケーションとDatetimeIndexの両方を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
_
31
Ted Petrou

複数列グループ化

untubuは彼の答えにスポットを当てていますが、3番目の列(Costなど)があり、上記のように集約したい場合にできることを追加したかったのです。 unutbuの答えと this one を組み合わせることで、これを行う方法を見つけ、将来のユーザーのために共有することを考えました。

Cost列を持つDataFrameを作成します。

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

次に、最後のunstackNaNをゼロで埋め、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
8