パンダを使用して時系列データの重複時間をどのように処理する必要がありますか?

2017年05月23日に質問されました。  ·  閲覧回数 2.9k回  ·  ソース

user7186882 picture
2017年05月23日

より大きなデータセットの一部として、API呼び出しから次のものが返されます。

{'時間':datetime.datetime(2017、5、21、18、18、1、tzinfo = tzutc())、 '価格': '0.052600'}

{'時間':datetime.datetime(2017、5、21、18、18、1、tzinfo = tzutc())、 '価格': '0.052500'}

理想的には、タイムスタンプをpandasデータフレームのインデックスとして使用しますが、JSONに変換するときに重複があるため、これは失敗するように見えます。

df = df.set_index(pd.to_datetime(df['Timestamp']))
print(new_df.to_json(orient='index'))

ValueError:DataFrameインデックスはorient = 'index'に対して一意である必要があります。

この状況に対処するための最良の方法に関するガイダンスはありますか? 1つのデータポイントを破棄しますか? 時間は秒よりもきめ細かくなりません、そして明らかにその秒の間に価格の変化があります。

回答

jezrael picture
2017年05月23日
6

mscumcountto_timedelta追加することで、重複する日時を変更できると思います。

d = [{'Time': datetime.datetime(2017, 5, 21, 18, 18, 1), 'Price': '0.052600'},
     {'Time': datetime.datetime(2017, 5, 21, 18, 18, 1), 'Price': '0.052500'}]
df = pd.DataFrame(d)
print (df)
      Price                Time
0  0.052600 2017-05-21 18:18:01
1  0.052500 2017-05-21 18:18:01

print (pd.to_timedelta(df.groupby('Time').cumcount(), unit='ms'))
0          00:00:00
1   00:00:00.001000
dtype: timedelta64[ns]

df['Time'] = df['Time'] + pd.to_timedelta(df.groupby('Time').cumcount(), unit='ms')
print (df)
      Price                    Time
0  0.052600 2017-05-21 18:18:01.000
1  0.052500 2017-05-21 18:18:01.001

new_df = df.set_index('Time')
print(new_df.to_json(orient='index'))
{"1495390681000":{"Price":"0.052600"},"1495390681001":{"Price":"0.052500"}}
ardms picture
2017年05月23日
0

.duplicatedを使用して、最初または最後のエントリを保持できます。 pandas.DataFrame.duplicatedをご覧ください

Danielle Madeley picture
2019年12月11日
0

受け入れられた答えを拡張するだけです。ループを追加すると、最初のパスで導入された新しい重複を処理するのに役立ちます。

このisnullは、データ内のNaTをキャッチするために重要です。 タイムデルタ+ NaTはまだNaTなので。

def deduplicate_start_times(frame, col='start_time', max_iterations=10):
    """
    Fuzz duplicate start times from a frame so we can stack and unstack
    this frame.
    """

    for _ in range(max_iterations):
        dups = frame.duplicated(subset=col) & ~pandas.isnull(frame[col])

        if not dups.any():
            break

        LOGGER.debug("Removing %i duplicates", dups.sum())

        # Add several ms of time to each time
        frame[col] += pandas.to_timedelta(frame.groupby(col).cumcount(),
                                          unit='ms')

    else:
        LOGGER.error("Exceeded max iterations removing duplicates. "
                     "%i duplicates remain", dups.sum())

    return frame