-
最終目標
Python, Pandasでlogファイルの時系列解析 -
実現したいこと
時系列DataFrameにおいて、特定列に含まれるキーワードにより行を抽出
具体的には、列名"Refid"に"PPS"というキーワードが含まれれば、その行を抽出
質問者背景
・Python初学者
・開発経験 Excel VBAのみ
(Original) logデータ
(前処理後) logデータ
前処理は最下部記載のコードをご参照。
Date Time(UTC) | Refid | Raw offset | Cooked offset | Disp. | |
---|---|---|---|---|---|
0 | 2019-05-25 16:51:22.999972 | PPSx | 2.731100e-05 | 0.000027 | 1.000000e-09 |
1 | 2019-05-25 16:51:22.323771 | NMEA | -3.237718e-01 | 0.176228 | 1.000000e-03 |
2 | 2019-05-25 16:51:23.999975 | PPS | 2.434500e-05 | 0.000024 | 1.000000e-09 |
3 | 2019-05-25 16:51:23.999975 | PPSx | 2.434500e-05 | 0.000024 | 1.000000e-09 |
4 | 2019-05-25 16:51:23.324379 | NMEA | -3.243791e-01 | 0.175621 | 1.000000e-03 |
5 | 2019-05-25 16:51:24.999973 | PPS | 2.658800e-05 | 0.000027 | 1.000000e-09 |
6 | 2019-05-25 16:51:24.999973 | PPSx | 2.658800e-05 | 0.000027 | 1.000000e-09 |
** 各列の型**
Jupyter
In[]: df.dtypes
Out[]:
Date Time(UTC) datetime64[ns]
Refid object
Raw offset float64
Cooked offset float64
Disp. float64
dtype: object
【理想】抽出後のDataFrame
Date Time(UTC) | Refid | Raw offset | Cooked offset | Disp. | |
---|---|---|---|---|---|
2 | 2019-05-25 16:51:23.999975 | PPS | 2.434500e-05 | 0.000024 | 1.000000e-09 |
5 | 2019-05-25 16:51:24.999973 | PPS | 2.658800e-05 | 0.000027 | 1.000000e-09 |
【現状】抽出失敗したDataFrame
- 試したこと1(→ 正常動作を確認)
DataFrameに時系列を含まなければ、上記の理想通りとなるが、
時系列を含むと以下のようなる。
Jupyter
In[]: df[df['Refid'] == 'PPS']
Out[]:
||Date Time(UTC)|Refid|Raw offset|Cooked offset|Disp.|
|:--|:--|:--|
|0|NaT|NaN|NaN|NaN|NaN|
|1|NaT|NaN|NaN|NaN|NaN|
|2|NaT|PPS|NaN|NaN|NaN|
|3|NaT|NaN|NaN|NaN|NaN|
|4|NaT|NaN|NaN|NaN|NaN|
|5|NaT|PPS|NaN|NaN|NaN|
|6|NaT|NaN|NaN|NaN|NaN|
↑logファイル前処理のバグが原因だった
- 試したこと2(→ 正常動作を確認)
Jupyter
In[]: df.query('Refid' == 'PPS')
Out[]:
...
ValueError: expr must be a string to be evaluated, <class 'bool'> given
** ↑logファイル前処理のバグが原因だった**
【解決済】Code
Python
import numpy as np import pandas as pd import re #正規表現 path = "D:\refclocks.log" # 列名の取得 # logファイル先頭3行から抽出 def get_Header(f): c = 0 for a in f: if '=' not in a: a = a.lstrip(' ') #文字列先頭の半角スペースを削除 s = re.sub(r" +", ",", a) s = s.replace("Date,(UTC),Time,", "Date Time(UTC),") #1列目と2列目を結合 s = s.replace("Raw,offset,", "Raw offset,") s = s.replace("Cooked,offset,", "Cooked offset,") s = s.replace("\n", "") #改行コードの除去 s = s.split(",") del s[2:5] #不要な列の削除 c += 1 if c == 3: break return s def get_Body(f, body): # ファイル先頭以外に定期的に含まれる列名(3行連続)は無視 for a in f: if '=' not in a: if a[0] != ' ': s = re.sub(r" +", ",", a) #複数半角スペース → 1つの半角スペース s = s.replace("\n", "") #改行コードの除去 s = s.split(",") tmp = s[0] + ' ' + s[1] #1列目と2列目を結合 s[0] = tmp del s[1] #不要な列の削除 del s[2:5] body.append(s) return body def main(): f = open(path, mode='rt') # /// 前処理 /// #列名(リスト)の取得 header = get_Header(f) #ファイルボディの取得 body = [] get_Body(f, body) f.close() #List --> Pandas DataFrameに変換 df = pd.DataFrame(body, dtype=float) df.columns = header #columnsの指定 (← get_Header関数を修正) #Cast df['Date Time(UTC)'] = pd.to_datetime(df['Date Time(UTC)']) df['Raw offset'] = df['Disp.'].astype(float) # /// 行の抽出 /// #試したこと1 ←正常動作 print(df[df['Refid'] == 'PPS']) #試したこと2 ←正常動作 print(df.query("Refid == 'PPS'")) if __name__ == '__main__': main()
###環境
Windows 10
Anaconda (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)]
Python: 3.7.3, Pandas: 0.24.2
Jupyter Notebook
まだ回答がついていません
会員登録して回答してみよう