-
最終目標
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
1In[]: 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
1In[]: 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
1In[]: df.query('Refid' == 'PPS')
Out[]:
...
ValueError: expr must be a string to be evaluated, <class 'bool'> given
** ↑logファイル前処理のバグが原因だった**
【解決済】Code
Python
1import numpy as np 2import pandas as pd 3import re #正規表現 4 5path = "D:\refclocks.log" 6 7# 列名の取得 8# logファイル先頭3行から抽出 9def get_Header(f): 10 c = 0 11 for a in f: 12 if '=' not in a: 13 a = a.lstrip(' ') #文字列先頭の半角スペースを削除 14 s = re.sub(r" +", ",", a) 15 s = s.replace("Date,(UTC),Time,", "Date Time(UTC),") #1列目と2列目を結合 16 s = s.replace("Raw,offset,", "Raw offset,") 17 s = s.replace("Cooked,offset,", "Cooked offset,") 18 s = s.replace("\n", "") #改行コードの除去 19 s = s.split(",") 20 del s[2:5] #不要な列の削除 21 22 c += 1 23 if c == 3: 24 break 25 26 return s 27 28def get_Body(f, body): 29# ファイル先頭以外に定期的に含まれる列名(3行連続)は無視 30 for a in f: 31 if '=' not in a: 32 if a[0] != ' ': 33 s = re.sub(r" +", ",", a) #複数半角スペース → 1つの半角スペース 34 s = s.replace("\n", "") #改行コードの除去 35 s = s.split(",") 36 tmp = s[0] + ' ' + s[1] #1列目と2列目を結合 37 s[0] = tmp 38 del s[1] #不要な列の削除 39 del s[2:5] 40 body.append(s) 41 42 return body 43 44def main(): 45 f = open(path, mode='rt') 46 47# /// 前処理 /// 48 #列名(リスト)の取得 49 header = get_Header(f) 50 51 #ファイルボディの取得 52 body = [] 53 get_Body(f, body) 54 55 f.close() 56 57 #List --> Pandas DataFrameに変換 58 df = pd.DataFrame(body, dtype=float) 59 df.columns = header #columnsの指定 (← get_Header関数を修正) 60 61 #Cast 62 df['Date Time(UTC)'] = pd.to_datetime(df['Date Time(UTC)']) 63 df['Raw offset'] = df['Disp.'].astype(float) 64 65 66# /// 行の抽出 /// 67 #試したこと1 ←正常動作 68 print(df[df['Refid'] == 'PPS']) 69 70 #試したこと2 ←正常動作 71 print(df.query("Refid == 'PPS'")) 72 73if __name__ == '__main__': 74 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

回答2件
あなたの回答
tips
プレビュー