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

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

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

JupyterLabは、Jupyter notebookの後継の対話型開発環境(IDE)です。データの可視化がインタラクティブで、プラグイン作成により新しいコンポーネントの追加および既存のコンポーネントも統合可能。サーバに閉じているため、データ分析に向いています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

2回答

781閲覧

欠損のある時系列データ

ot24

総合スコア4

JupyterLab

JupyterLabは、Jupyter notebookの後継の対話型開発環境(IDE)です。データの可視化がインタラクティブで、プラグイン作成により新しいコンポーネントの追加および既存のコンポーネントも統合可能。サーバに閉じているため、データ分析に向いています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2022/04/24 15:26

前提

python pandas にて時系列の処理を行うにあたり、ある期間の欠損のあるデータを一日毎のデータとしたい、また、あるカラムのデータの順に並ぶようにしたいです。

実現したいこと

以下のように、現在のDataframeから欲しいDataframeのようにある決めた期間(今回ですと2000/1/1-2000/1/10)の1日ごとのデータにし、現在のDataFrameのs_1の順に並ぶようにしたいです。また、s_2,s_3はs_1の値であらかじめ決まっているものとして、欲しいDataframeへは欠損値とせず値を引き継ぎたいと考えています。

現在のDataframe date,s_1,s_2,s_3,v_1,v_2 2000-01-03,A,3,8,0.6,1.1 2000-01-05,A,3,8,5.0,1.5 2000-01-06,A,3,8,3.1,1.7 2000-01-07,A,3,8,6.5,1.5 2000-01-01,B,5,2,5.9,1.3 2000-01-02,B,5,2,5.4,1.4 2000-01-04,B,5,2,5.6,1.3 2000-01-09,B,5,2,5.4,1.2 欲しいDataframe date,s_1,s_2,s_3,v_1,v_2 2000-01-01,A,3,8,NA,NA 2000-01-02,A,3,8,NA,NA 2000-01-03,A,3,8,0.6,1.1 2000-01-04,A,3,8,NA,NA 2000-01-05,A,3,8,5.0,1.5 2000-01-06,A,3,8,3.1,1.7 2000-01-07,A,3,8,6.5,1.5 2000-01-08,A,3,8,NA,NA 2000-01-09,A,3,8,NA,NA 2000-01-10,A,3,8,NA,NA 2000-01-01,B,5,2,5.9,1.3 2000-01-02,B,5,2,5.4,1.4 2000-01-03,B,5,2,NA,NA 2000-01-04,B,5,2,5.6,1.3 2000-01-05,B,5,2,NA,NA 2000-01-06,B,5,2,NA,NA 2000-01-07,B,5,2,NA,NA 2000-01-08,B,5,2,NA,nA 2000-01-09,B,5,2,5.4,1.2 2000-01-10,B,5,2,NA,NA

試したこと

以下が参考になるかと思いましたが、データの期間が元のデータの範囲に拠ってしまう点、また、引き継ぐ内容も"source"の一列だけで、今回のように複数(s_1,s_2,s_3)引き継ぐにはどのようにすべきかまで至りませんでした。

import io from textwrap import dedent import pandas as pd csv_data = dedent( """ date,source,value 2000-01-01,A,0.66691 2000-02-01,A,5.04412 2000-03-01,A,3.15062 2000-05-01,A,6.57241 2000-01-01,B,95.9277 2000-03-01,B,85.4801 2000-04-01,B,85.6996 2000-05-01,B,55.4857 """ ) df = pd.read_csv(io.StringIO(csv_data), index_col="date", parse_dates=True) # あとで順番を戻せるよう元々の列名リストを記憶しておく orig_colnames = [str(c) for c in df.columns] # source ごとに欠損日時のデータを NaN で埋める dfs = [] sources = df["source"].unique() for source in sources: # その source の時系列データだけを取り出す tmp = df[df["source"] == source].drop(columns="source") # 欠損行を補完 tmp = tmp.resample("D").asfreq() # あとで結合するために結果を記録 tmp["source"] = source dfs.append(tmp) # source ごとに欠損行を補完したデータフレーム群を結合 df = pd.concat(dfs) # 列の順番を元に戻す df = df.reindex(columns=orig_colnames) print(df)

リンク内容

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

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

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

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

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

guest

回答2

0

  • 連続する日の列をpd.date_range()で作成
  • s_1, s_2, s_3 のユニークなテーブルをdrop_duplicatesで作成
  • それらの直積をpd.merge(how='cross')で作成

これにより新しいテーブルのdate, s_1, s_2, s_3 が作れます。
(並び順がs1を優先しつつ、左をdateにするために、少しややこしいことをしています)

あとは、それに、元のデータをleft joinすれば、欲しい形になります。

python

1import pandas as pd 2from io import StringIO 3 4s = '''\ 5date,s_1,s_2,s_3,v_1,v_2 62000-01-03,A,3,8,0.6,1.1 72000-01-05,A,3,8,5.0,1.5 82000-01-06,A,3,8,3.1,1.7 92000-01-07,A,3,8,6.5,1.5 102000-01-01,B,5,2,5.9,1.3 112000-01-02,B,5,2,5.4,1.4 122000-01-04,B,5,2,5.6,1.3 132000-01-09,B,5,2,5.4,1.2 14''' 15 16df = pd.read_csv(StringIO(s), parse_dates=['date']) 17 18dates = pd.date_range('2000-01-01', '2000-01-10').to_series(name='date') 19s_uniq = df[['s_1', 's_2', 's_3']].drop_duplicates() 20new_index = pd.merge(s_uniq, dates, how='cross')[['date'] + s_uniq.columns.to_list()] 21 22df2 = pd.merge(new_index, df, how='left')

投稿2022/04/25 08:59

編集2022/04/25 10:17
bsdfan

総合スコア4560

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

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

ot24

2022/04/25 14:48

ご回答ありがとうございました。初心者の私でも比較的わかりやすい書き方で、非常に参考になりました。
guest

0

ベストアンサー

python

1import pandas as pd 2import io 3 4csv_data = ''' 5date,s_1,s_2,s_3,v_1,v_2 62000-01-03,A,3,8,0.6,1.1 72000-01-05,A,3,8,5.0,1.5 82000-01-06,A,3,8,3.1,1.7 92000-01-07,A,3,8,6.5,1.5 102000-01-01,B,5,2,5.9,1.3 112000-01-02,B,5,2,5.4,1.4 122000-01-04,B,5,2,5.6,1.3 132000-01-09,B,5,2,5.4,1.2 14''' 15df = pd.read_csv(io.StringIO(csv_data), parse_dates=['date']) 16 17# 18idx = pd.date_range('2000-01-01', '2000-01-10') 19# idx = pd.date_range(df['date'].min(), df['date'].max()) 20dfx = ( 21 df.groupby('s_1', as_index=False) 22 .apply(lambda x: x.set_index('date').reindex(idx)) 23 .droplevel(0).rename_axis('date').reset_index()) 24 25cols = df.filter(regex=r'^s_').columns 26dfx[cols] = dfx[cols].ffill().bfill() 27print(dfx) 28 29# 30 date s_1 s_2 s_3 v_1 v_2 310 2000-01-01 A 3.0 8.0 NaN NaN 321 2000-01-02 A 3.0 8.0 NaN NaN 332 2000-01-03 A 3.0 8.0 0.6 1.1 343 2000-01-04 A 3.0 8.0 NaN NaN 354 2000-01-05 A 3.0 8.0 5.0 1.5 365 2000-01-06 A 3.0 8.0 3.1 1.7 376 2000-01-07 A 3.0 8.0 6.5 1.5 387 2000-01-08 A 3.0 8.0 NaN NaN 398 2000-01-09 A 3.0 8.0 NaN NaN 409 2000-01-10 A 3.0 8.0 NaN NaN 4110 2000-01-01 B 5.0 2.0 5.9 1.3 4211 2000-01-02 B 5.0 2.0 5.4 1.4 4312 2000-01-03 B 5.0 2.0 NaN NaN 4413 2000-01-04 B 5.0 2.0 5.6 1.3 4514 2000-01-05 B 5.0 2.0 NaN NaN 4615 2000-01-06 B 5.0 2.0 NaN NaN 4716 2000-01-07 B 5.0 2.0 NaN NaN 4817 2000-01-08 B 5.0 2.0 NaN NaN 4918 2000-01-09 B 5.0 2.0 5.4 1.2 5019 2000-01-10 B 5.0 2.0 NaN NaN

投稿2022/04/25 02:02

melian

総合スコア19714

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

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

ot24

2022/04/25 14:47

ご回答ありがとうございました。dfxを作成しておきffill,bfillする方法がシンプルな書き方に見えましたのでベストアンサーとさせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問