前提・実現したいこと
以下のようなcsvファイルにおいてdateおよびtime列の欠損を補完した上で,新しいcsvファイルとして出力する方法を模索しています.もし可能であればこの操作をGoogleColab上で実行したいと考えています.
元データは水文水質データベースのダム諸量から取得しており,全てで8年分です.
](3e32e2af074d1c9e553d1de436cec8c8.png)
発生している問題
・dateおよびtime列に欠損が多数存在しており,補完する効率的な方法が必要
※欠損している時間は空白のセルや欠損値が存在するわけではなく,そもそも行が存在しません.あたかも連続したデータであるかのようになっています.
(補完した際は,dateおよびtime列以外にNaNを入力したい)
・time列において,0:00のみが1900/1/1 0:00と入力されており,これをExcelのフィル機能を用いて書き換えると,時系列に矛盾が生じてしまう(画像参照)
補足情報
Colab上での実行については自己学習のための願望ですので,Pythonを用いた解決方法でなくても全く問題ありません.
同時に2つの質問してしまっているような形になってしまい申し訳ありませんが,よろしくお願いします.
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
例えば、
CSV
1discharge,date,time,storage,inflow 214.64,2012/7/1,1:00,235,14.64 314.64,2012/7/1,2:00,244,16.04 414.64,2012/7/1,3:00,244,15.58 514.64,2012/7/1,5:00,244,14.64
のようなCSVファイルの場合、pandas.read_csv()
にて、下記のように、
parse_dates={'datetime':['date','time']}
パラメータを指定してデータを読み込むことで、'date'列と'time'列をまとめて'datetime'列を作成してdatetime型のデータとして読み込むこ とができます。
さらに
index_col='datetime'
パラメータを追加することで、上記で作成した'datetime'列をIndex行に指定できます。
Python
1df = pd.read_csv('data.csv', parse_dates={'datetime':['date','time']}, index_col='datetime') 2print(df) 3# discharge storage inflow 4#datetime 5#2012-07-01 01:00:00 14.64 235 14.64 6#2012-07-01 02:00:00 14.64 244 16.04 7#2012-07-01 03:00:00 14.64 244 15.58 8#2012-07-01 05:00:00 14.64 244 14.64
補足として、上記を通常のDataFrame操作で説明すると
Python
1df = pd.read_csv('data.csv') 2# date列とtime列を結合し、datetime型のデータに変換 3df['datetime'] = pd.to_datetime(df['date'] + ' ' + df['time']) 4# date列とtime列は不要なので削除 5df = df.drop(['date', 'time'], axis=1) 6# datetime列をIndexに設定 7df = df.set_index('datetime')
という感じでになります。
このようにDateTimeIndex(Datetime型のIndex)の作成ができると、あとは x98000さんが書かれております通り、DataFrame.asfreq()
を使ってデータを1時間間隔で揃えることができるかと思います。
Python
1df = df.asfreq('1H') 2print(df) 3# discharge storage inflow 4#datetime 5#2012-07-01 01:00:00 14.64 235.0 14.64 6#2012-07-01 02:00:00 14.64 244.0 16.04 7#2012-07-01 03:00:00 14.64 244.0 15.58 8#2012-07-01 04:00:00 NaN NaN NaN 9#2012-07-01 05:00:00 14.64 244.0 14.64
投稿2020/05/20 05:41
総合スコア15898
0
こちらはどの様なプログラミング言語での解決をお望みなのでしょうか。
Excel-VBAであれば、面白そうなのでサンプルを作ってみました。
但し、下記事項は私には解決できません。
>もし可能であればこの操作をGoogleColab上で実行したいと考えています.
>Pythonを用いた解決方法
ExcelVBAの作成条件は下記のようなCSVファイルデータを想定。
また、時刻部分は文字列として扱っています。
csvファイルを起動し、シートのVBAへ張り付け実行で動く筈です。
作成環境:Excel2010(32bit)
'----------------------------------
discharge,date,time,strage,inflow
14.95,2020/7/1,1:00:00,266,14.92
14.96,2020/7/1,2:00:00,267,14.93
14.97,2020/7/1,3:00:00,268,14.94
・
・
'----------------------------------
Sub Test_Sample_Miniature() Dim MyStartDate As Range Dim MyStartTime As Range Dim MySherchArea As Range Dim dtmCsvDate As Date Dim dtmAddDate As Date Dim strCsvTime As String Dim intCsvTimeCnt As Integer Dim intAddTimeCnt As Integer Dim MyRange As Range Dim WrkRange As Range Dim lStaRow As Long Dim lEndRow As Long Dim lCol As Long Dim lX As Long '定義 Set MyStartDate = Range("B2") Set MyStartTime = Range("C2") Set MySherchArea = Range("B2:B99") '初期値 lStaRow = MySherchArea.Row lEndRow = lStaRo + MySherchArea.Rows.Count - 1 lCol = MySherchArea.Column ' dtmCsvDate = CDate(MyStartDate) dtmAddDate = CDate(dtmCsvDate) intCsvTimeCnt = CInt(Left(MyStartTime.Text, InStr(MyStartTime.Text, ":") - 1)) intAddTimeCnt = intCsvTimeCnt lStaRow = lStaRow + 1 If intCsvTimeCnt = 24 Then MsgBox "24時からの開始は不可": Exit Sub Cells(lStaRow - 1, 3) = "'" & Cells(lStaRow - 1, 3).Text '開始 For lX = lStaRow To lEndRow ' Set MyRange = Cells(lX, lCol) If IsDate(MyRange) = False Then Exit For ' strCsvTime = Cells(MyRange.Row, MyRange.Column + 1).Text intCsvTimeCnt = CInt(Left(strCsvTime, InStr(strCsvTime, ":") - 1)) intAddTimeCnt = intAddTimeCnt + 1 ' If dtmCsvDate > CDate(MyRange) Then MsgBox "古い日付が出現終了": Exit For dtmCsvDate = CDate(MyRange) If intAddTimeCnt = 1 Then dtmAddDate = DateAdd("d", dtmAddDate, 1) ' '判定と行挿入 If dtmCsvDate <> dtmAddDate Or intCsvTimeCnt <> intAddTimeCnt Then ' '行挿入と値セット Rows(MyRange.Row).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove Cells(MyRange.Row - 1, 1) = "NaN" Cells(MyRange.Row - 1, 2) = dtmAddDate Cells(MyRange.Row - 1, 3) = "'" & CStr(intAddTimeCnt) & ":00:00" Cells(MyRange.Row - 1, 4) = "NaN" Cells(MyRange.Row - 1, 5) = "NaN" ' '行挿入の為基準値変更 intCsvTimeCnt = intAddTimeCnt dtmCsvDate = dtmAddDate lEndRow = lEndRow + 1 ' Else Cells(lX, 3) = "'" & Cells(lX, 3).Text End If ' If intAddTimeCnt = 24 Then intAddTimeCnt = 0 ' Next 'Range解放 Set MyStartDate = Nothing Set MyStartTime = Nothing Set MySherchArea = Nothing Set MyRange = Nothing Set WrkRange = Nothing End Sub
投稿2020/05/20 05:19
編集2020/05/22 00:01総合スコア553
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
pandasに取り込み、日時をTimestamp型のindexに変換すれば、
pandas
1# 1H毎にデータを補間する 2df.asfreq('1H')
で、複数行の欠損があっても埋めてくれますし、重複データをまとめることも出来ます。
デフォルトでは不足データをNaNで埋めますが、任意の値や前後の値で埋めることも出来ます。
また、df.resample()
を使うと線形補間などを行うことも出来ます。
調べてみてください。
投稿2020/05/19 22:10
総合スコア1096
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/22 17:42
2020/05/23 20:23 編集