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

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

新規登録して質問してみよう
ただいま回答率
85.35%
データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4441閲覧

時系列データで、時間の歯抜けと欠損のあるデータ

f_05

総合スコア2

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/07/30 08:38

前提・実現したいこと

時系列で、1時間ごとに以下のような形式でデータの入っているものがあります。

datetime on_off
2020-05-31 11:31           00000000000000000000000000000
2020-05-31 12:00 000000000000000000000000000000000000000000000000000000000000
2020-06-01 13:00 111111000100000111100000000000000000000000000000000000000000
2020-06-03 14:18       000000000000000000000000000000000000000000
2020-06-05 15:00 000000000000000000000000000000000000000000000000000000000000
2020-06-06 03:00 000000000000000000000000000000000000000000000000000000000000

前提条件として、
・欠損している箇所には空白もNaNも入っておらず、値として入ってるのは数字が始まる部分から
・「on/off」データは一行に60個あるのが正常なもの
・datetimeで「11:31」のように途中から始まってる場合は[on/off]列は31分から始まるので29個値が並ぶ

出したい形としては、

2020-04-13 11:31:00 0
2020-04-13 11:32:00 0
2020-04-13 11:33:00 0
2020-04-13 11:34:00 0
[省略]
2020-04-13 11:59:00 0

のように毎分1レコードのように対応させたいのです。

該当のソースコード

python

1start_at, end_at = df.datetime.min(), df.datetime.max() 2res = df.reindex(pd.date_range(start_at, end_at, freq="T"))

で、まず分毎のデータを作成し、

python

1df["on_off"].str.split('') 2list_split =[[a for a in y if a != '']for y in y]

でリスト化して結合することで対応しようとしたのですが、日にち自体も歯抜けしている為に二つの数が合わず、
結合ができませんでした。

このようなデータに対してアプローチ自体が間違えてるのでしょうか・・・。
何卒よろしくお願いします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

スマートな回答ではないですが、行ごとにループして作成するのはどうでしょうか。

python

1import pandas as pd 2from io import StringIO 3 4# 設問のDataFrameを用意 5input_str = """ 6datetime on_off 72020-05-31T11:31 00000000000000000000000000000 82020-05-31T12:00 000000000000000000000000000000000000000000000000000000000000 92020-06-01T13:00 111111000100000111100000000000000000000000000000000000000000 102020-06-03T14:18 000000000000000000000000000000000000000000 112020-06-05T15:00 000000000000000000000000000000000000000000000000000000000000 122020-06-06T03:00 000000000000000000000000000000000000000000000000000000000000 13""" 14df = pd.read_csv(StringIO(input_str), delim_whitespace=True) 15 16 17res = pd.DataFrame({"on_off": []}) 18for i, row in df.iterrows(): 19 data = list(row["on_off"]) 20 index = pd.date_range(start=row["datetime"], periods=len(data), freq="60s") 21 df_part = pd.DataFrame({"on_off": data}, index=index) 22 res = pd.concat([res, df_part]) 23 24# 間の時間をNaNで埋めたい場合、リサンプリングする(しない場合は不要) 25res = res.resample("60s").asfreq()

投稿2020/07/30 13:53

yymmt

総合スコア1615

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

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

f_05

2020/07/31 07:10

こんなに短い処理で書けるんですね・・・!動かしてみたらすぐ欲しい時間データを抽出出来ました! ありがとうございます!!
guest

0

ベストアンサー

基本的なpandasのコードで実装しました。
そのままコピペして頂ければ動きます。

python

1# 各種インポート 2import pandas as pd, numpy as np 3from datetime import datetime 4import datetime 5import itertools

python

1# データフレームの作成 2a = ['2020-05-31 11:31', '2020-05-31 12:00', '2020-06-01 13:00', '2020-06-03 14:18', '2020-06-05 15:00', '2020-06-06 03:00'] 3b = ['00000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000', '111111000100000111100000000000000000000000000000000000000000', 4 '000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000'] 5c = {"datetime": a, "on_off": b} 6df = pd.DataFrame.from_dict(c)

python

1# datetimeのデータ型をdatetime型に変更 2df.datetime = pd.to_datetime(df['datetime'])

python

1# データフレームの確認 2df

python

1# 必要な時刻のインデックスを持つ、空のテーブルを作成します 2data = pd.DataFrame(columns=['on_off']) # 空のデータフレームを作成 3for i in range(len(df)): # データフレームを1行ずつ取り出します 4 start_at = df.loc[i].datetime # datetimeの値をそのままstart_atにします 5 end_at = df.loc[i].datetime + datetime.timedelta(minutes=len(df.loc[i].on_off)-1) # on_offに含まれている文字数-1分をstart_atに加算してend_atとします 6 res = df.reindex(pd.date_range(start_at, end_at, freq="T")) # 例えば1列目だと、start_atが11:31:00、end_atが11:59:00となる 7 res = res.drop(columns='datetime') 8 data = data.append(res) # 空のデータフレームに作成したテーブルを追加する

python

1# on_offの文字列を取り出していきます 2lis = [] # 空のリストを作成します 3for i in range(len(df)): 4 lis.append(list(df.on_off.loc[i])) # list(文字列)とするとバラバラにできます 5lis = list(itertools.chain.from_iterable(lis)) # 2次元のリストをitertoolsを使って1次元のリストに変換します 6print(lis)

python

1# 作成したdataとlisを組み合わせます 2data.on_off = lis

python

1# dataを確認します。これで必要なテーブルが手に入りました。 2data

投稿2020/07/30 15:46

編集2020/07/30 15:52
keisuke0919

総合スコア34

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

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

f_05

2020/07/31 07:04

すごく丁寧に教えて頂きありがとうございます・・・!! コメントアウトで処理してる内容も詳しく書いて頂いたので、一つずつ動かして納得しながら進められました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問