質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Pylons

Pylonsは、Pythonで書かれたオープンソースのWebアプリケーションフレームワークです。 主要コンポーネントの一部は、Ruby on Railsの機能をPythonで再実装したものです。

Q&A

1回答

218閲覧

タイムスタンプのデータ補完の仕方を教えてください

yu_ttot

総合スコア1

Pylons

Pylonsは、Pythonで書かれたオープンソースのWebアプリケーションフレームワークです。 主要コンポーネントの一部は、Ruby on Railsの機能をPythonで再実装したものです。

0グッド

0クリップ

投稿2024/02/21 08:22

実現したいこと

下記のようなデータを
date_strs = ['2020-01-01 12:00:00', '2020-01-01 12:00:00', '2020-01-01 12:00:58 005', '2020-01-01 12:01:00', '2020-01-01 12:01:00', '2020-01-01 12:00:00', '2020-01-01 12:00:00', '2020-01-01 12:00:45 008', '2020-01-01 12:00:00', '2020-01-01 12:00:00']
下記のようにミリセックがないデータを3秒周期で補完したいです。
ただ、時系列順に並んでいない場合もあるため前にも同じ分数がある場合は以降に出てくるミリセックが含まれているデータをもとに補完したいです。
[Timestamp('2020-01-01 12:00:52'),
Timestamp('2020-01-01 12:00:55'),
Timestamp('2020-01-01 12:00:58'),
Timestamp('2020-01-01 12:01:01'),
Timestamp('2020-01-01 12:01:04'),
Timestamp('2020-01-01 12:00:39'),
Timestamp('2020-01-01 12:00:42'),
Timestamp('2020-01-01 12:00:45'),
Timestamp('2020-01-01 12:00:48'),
Timestamp('2020-01-01 12:00:51')]

前提

ここに質問の内容を詳しく書いてください。
(例)
現状、下記のプログラムを実行すると
[Timestamp('2020-01-01 12:00:52'),
Timestamp('2020-01-01 12:00:55'),
Timestamp('2020-01-01 12:00:58'),
Timestamp('2020-01-01 12:01:01'),
Timestamp('2020-01-01 12:01:04'),
Timestamp('2020-01-01 12:01:07'),
Timestamp('2020-01-01 12:01:10'),
Timestamp('2020-01-01 12:00:45'),
Timestamp('2020-01-01 12:00:48'),
Timestamp('2020-01-01 12:00:51')]
のようにうまく補完できません。

該当のソースコード

import pandas as pd def adjust_and_complete_timestamps_with_comparison(date_strs, format='%Y-%m-%d %H:%M:%S %f'): parsed_dates = [] # 解析済みの日時を格納するリスト last_completed_date = None # 最後に補完された日時 for date_str in date_strs: try: current_date = pd.to_datetime(date_str, format=format, errors='raise').replace(microsecond=0) parsed_dates.append(current_date) last_completed_date = current_date except ValueError: if last_completed_date is not None: # 直前に補完された日時から3秒後の日時を提案 proposed_date = last_completed_date + pd.Timedelta(seconds=3) if parsed_dates and proposed_date.minute < last_completed_date.minute: # 直後の有効な日時を探す for future_date_str in date_strs[len(parsed_dates):]: try: future_date = pd.to_datetime(future_date_str, format=format, errors='raise').replace(microsecond=0) # 直後の有効な日時から適切な補完を行う diff = (future_date - proposed_date).total_seconds() // 3 proposed_date = future_date - pd.Timedelta(seconds=3 * diff) break except ValueError: continue parsed_dates.append(proposed_date) last_completed_date = proposed_date else: # 最初の有効な日時がまだ見つかっていない場合 parsed_dates.append(None) # None値を補完 for i in range(len(parsed_dates)): if parsed_dates[i] is None: # 直後の有効な日時から逆算して補完 for j in range(i + 1, len(parsed_dates)): if parsed_dates[j] is not None: parsed_dates[i] = parsed_dates[j] - pd.Timedelta(seconds=3 * (j - i)) break return parsed_dates # 使用例 date_strs = ['2020-01-01 12:00:00', '2020-01-01 12:00:00', '2020-01-01 12:00:58 005', '2020-01-01 12:01:00', '2020-01-01 12:01:00', '2020-01-01 12:00:00', '2020-01-01 12:00:00', '2020-01-01 12:00:45 008', '2020-01-01 12:00:00', '2020-01-01 12:00:00'] adjusted_dates_with_comparison = adjust_and_complete_timestamps_with_comparison(date_strs) adjusted_dates_with_comparison

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroki-o

2024/02/21 21:44

もし、こういうデータだったら、どうなるのが正解ですか?そうならない前提? date_strs = ['2020-01-01 12:00:00', '2020-01-01 12:00:00', '2020-01-01 12:00:58 005', '2020-01-01 12:01:00', '2020-01-01 12:01:00', '2020-01-01 12:01:00', '2020-01-01 12:01:00', '2020-01-01 12:01:45 008', '2020-01-01 12:01:00', '2020-01-01 12:01:00']
guest

回答1

0

ミリ秒が含まれているデータをもとに補完したい

python

1import pandas as pd 2 3date_strs = [ 4 '2020-01-01 12:00:00', '2020-01-01 12:00:00', '2020-01-01 12:00:58 005', 5 '2020-01-01 12:01:00', '2020-01-01 12:01:00', '2020-01-01 12:00:00', 6 '2020-01-01 12:00:00', '2020-01-01 12:00:45 008', '2020-01-01 12:00:00', 7 '2020-01-01 12:00:00'] 8 9s1 = pd.to_datetime(pd.Series(date_strs), format='%Y-%m-%d %H:%M:%S', errors='coerce') 10gid = (s1.notna() & s1.diff().dt.total_seconds().ne(0)).cumsum() 11gid += s1.groupby(gid, group_keys=False).transform(lambda s: s.isna().any()) 12 13s2 = pd.to_datetime(pd.Series(date_strs), format='%Y-%m-%d %H:%M:%S %f', errors='coerce').dt.floor('s') 14s2 = s2.groupby(gid, group_keys=False)\ 15 .apply(lambda s: 16 s1[s.index] if (idx := s.first_valid_index()) is None 17 else pd.date_range(s[idx] - (idx - s.index[0]) * pd.Timedelta('3s'), 18 freq='3s', periods=len(s)).to_series().set_axis(s.index)) 19 20 21print(s2) 22 23# 0 2020-01-01 12:00:52 24# 1 2020-01-01 12:00:55 25# 2 2020-01-01 12:00:58 26# 3 2020-01-01 12:01:01 27# 4 2020-01-01 12:01:04 28# 5 2020-01-01 12:00:39 29# 6 2020-01-01 12:00:42 30# 7 2020-01-01 12:00:45 31# 8 2020-01-01 12:00:48 32# 9 2020-01-01 12:00:51 33# dtype: datetime64[ns]

投稿2024/02/21 15:10

編集2024/02/21 16:33
melian

総合スコア20675

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問