以下の場合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()のさまざまな組み合わせを試しましたが、運はありません。これについてどうすればいいですか?
元の投稿で、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
これを行うには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
_
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
次に、最後の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