パンダ日時インデックス:現在のイベントの数時間をかけて

user1680772:

私はタイプ、開始、および終了タイムスタンプを持っているそれぞれのイベントのセットを、分析しています。私は、時間範囲にわたって、進行中の各イベントの時間の同時数を要約しようとしています。

、イベント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_countsSeries.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

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=373014&siteId=1