私はタイプ、開始、および終了タイムスタンプを持っているそれぞれのイベントのセットを、分析しています。私は、時間範囲にわたって、進行中の各イベントの時間の同時数を要約しようとしています。
、イベントN1-N4をリストアップ、重なり合う範囲でそれぞれを以下のデータセットを考えてみましょう:
>>> data = {
... 'name' : [ 'N1', 'N2', 'N3', 'N4', 'N1', 'N2', 'N7'],
... 'start_dt_str' : ['01-01-2020', '01-03-2020', '01-01-2020', '01-01-2020', '01-03-2020', '01-04-2020','01-10-2020'],
... 'end_dt_str' : ['01-03-2020', '01-05-2020', '01-05-2020', '01-02-2020', '01-04-2020', '01-05-2020', '01-11-2020']
... }
>>> df = pd.DataFrame(data)
>>> df['start_dt'] = pd.to_datetime(df['start_dt_str'])
>>> df['end_dt'] = pd.to_datetime(df['end_dt_str'])
>>> del df['start_dt_str']
>>> del df['end_dt_str']
>>> df
name start_dt end_dt
0 N1 2020-01-01 2020-01-03
1 N2 2020-01-03 2020-01-05
2 N3 2020-01-01 2020-01-05
3 N4 2020-01-01 2020-01-02
4 N1 2020-01-03 2020-01-04
5 N2 2020-01-04 2020-01-05
6 N7 2020-01-10 2020-01-11
私の目標は、範囲内の各日付のために、種類によって、この要約、同時イベントの数を生成することです。これは、正しい答えのようになります。
N1 N2 N3 N4 N7
2020-01-01 1 0 1 1 0
2020-01-02 1 0 1 1 0
2020-01-03 2 1 1 0 0
2020-01-04 1 2 1 0 0
2020-01-05 1 2 0 0 0
2020-01-06 0 0 0 0 0
2020-01-07 0 0 0 0 0
2020-01-08 0 0 0 0 0
2020-01-09 0 0 0 0 0
2020-01-10 0 0 0 0 1
2020-01-11 0 0 0 0 1
start_dtとend_dt列の両方に重複の日付があることに注意してください。
また、ソリューションがすべてゼロを含む行の塗りつぶし行方不明日付ようにデータを再サンプリングする機能を提供しなければならないことに注意してください。この例では、日付01-09は、開始日または終了日として表示されませんが、出力に存在している必要があります。一般的なケースでは、私は、任意の間隔を選択するために、再サンプリングを行うことができることを望みます。
問題の両方の報告期間とデータを説明を簡単にするために上記データセット内の日の精度です。実際のデータセットでは、start_dtとend_dtは(まだ重複が含まれている)ミリ秒の精度であり、かつ報告期間は、時間、日、週、等の可能性
また、そのリサンプリングは、日時シリーズを生産するために必要とされ、データ内にギャップがあることに注意してください。(IEは、データがmilliscond精度であるにも関わらず、不足している全体の日があります)。
私は動作しないいくつかのアプローチを試みました。まず、それはこれがシンプルになるように見えた、私が試しました:
df.set_index(['name','start_dt']).groupby('name').resample('D',level='start_dt').ffill()
ValueError: Upsampling from level= or on= selection is not supported, use .set_index(...) to explicitly set index to datetime-like
するためにどのリードこのパンダの問題アップサンプリングについてはオープンであり、いくつかの回避策を提供します。それは非一意であるため、残念ながら、私たちはインデックスとしてstart_dt(またはend_dt)のみを使用することはできません。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/core/resample.py", line 453, in pad
return self._upsample("pad", limit=limit)
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/core/resample.py", line 1095, in _upsample
res_index, method=method, limit=limit, fill_value=fill_value
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/util/_decorators.py", line 227, in wrapper
return func(*args, **kwargs)
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/core/frame.py", line 3856, in reindex
return super().reindex(**kwargs)
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/core/generic.py", line 4544, in reindex
axes, level, limit, tolerance, method, fill_value, copy
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/core/frame.py", line 3744, in _reindex_axes
index, method, copy, level, fill_value, limit, tolerance
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/core/frame.py", line 3760, in _reindex_index
new_index, method=method, level=level, limit=limit, tolerance=tolerance
File "/home/dcowden/envs/analysis-env/lib/python3.6/site-packages/pandas/core/indexes/base.py", line 3149, in reindex
"cannot reindex a non-unique index "
ValueError: cannot reindex a non-unique index with a method or limit
この質問私の問題に似ているようだが、各イベントタイプの範囲内の日付のすべてを埋めるdoesntの:
>>> df.set_index('start_dt').groupby('name').resample('D').asfreq()
name end_dt
name start_dt
N1 2020-01-01 N1 2020-01-03
2020-01-02 NaN NaT
2020-01-03 N1 2020-01-04
N2 2020-01-03 N2 2020-01-05
2020-01-04 N2 2020-01-05
N3 2020-01-01 N3 2020-01-05
N4 2020-01-01 N4 2020-01-02
このソリューションは有望に見えたが、私はどちらか必要なものを正確ではありません。それは本質的に範囲内の単一イベントを検索しますが、進行中の合計数をカウントしません。良いスタートのように見えるんIntervalIndexを使用してけれども。
これはかなり簡単なはずような気がしますが、明らかに私のパンダfooがはなはだ不十分です。
ヘルプははるかに高く評価されます!
EDIT:
アイデアは、あたりを繰り返した値であるdate_range
ヘルパーにDataFrame
してから使用しSeriesGroupBy.value_counts
てSeries.unstack
:
L = [pd.Series(r.name, pd.date_range(r.start_dt, r.end_dt)) for r in df.itertuples()]
s = pd.concat(L)
df1 = s.groupby(level=0).value_counts().unstack(fill_value=0)
print (df1)
N1 N2 N3 N4
2020-01-01 1 0 1 1
2020-01-02 1 0 1 1
2020-01-03 2 1 1 0
2020-01-04 1 2 1 0
2020-01-05 0 2 1 0
別によってリシェイプを伴う溶液DataFrame.melt
が、最初で連続した値を区別する必要があるSeries.shift
とのSeries.cumsum
トリック、そして使用DataFrameGroupBy.resample
し、最後crosstab
:
df['g'] = df['name'].ne(df['name'].shift()).cumsum()
df1 = (df.melt(['name','g'])
.set_index('value')
.groupby(['g','name'])['variable']
.resample('d')
.first()
.reset_index())
df1 = pd.crosstab(df1['value'], df1['name'])
print (df1)
name N1 N2 N3 N4
value
2020-01-01 1 0 1 1
2020-01-02 1 0 1 1
2020-01-03 2 1 1 0
2020-01-04 1 2 1 0
2020-01-05 0 2 1 0