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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

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

pandas

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

Q&A

解決済

2回答

1628閲覧

時系列DataFrameで特定列に含まれるキーワードにより行を抽出

Higomon

総合スコア33

Python 3.x

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

pandas

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

0グッド

0クリップ

投稿2019/07/10 06:56

編集2019/07/12 09:54
  • 最終目標
    Python, Pandasでlogファイルの時系列解析

  • 実現したいこと
    時系列DataFrameにおいて、特定列に含まれるキーワードにより行を抽出
    具体的には、列名"Refid"に"PPS"というキーワードが含まれれば、その行を抽出

質問者背景
・Python初学者
・開発経験 Excel VBAのみ

(Original) logデータ

refclocks.log

(前処理後) logデータ

前処理は最下部記載のコードをご参照。

Date Time(UTC)RefidRaw offsetCooked offsetDisp.
02019-05-25 16:51:22.999972PPSx2.731100e-050.0000271.000000e-09
12019-05-25 16:51:22.323771NMEA-3.237718e-010.1762281.000000e-03
22019-05-25 16:51:23.999975PPS2.434500e-050.0000241.000000e-09
32019-05-25 16:51:23.999975PPSx2.434500e-050.0000241.000000e-09
42019-05-25 16:51:23.324379NMEA-3.243791e-010.1756211.000000e-03
52019-05-25 16:51:24.999973PPS2.658800e-050.0000271.000000e-09
62019-05-25 16:51:24.999973PPSx2.658800e-050.0000271.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)RefidRaw offsetCooked offsetDisp.
22019-05-25 16:51:23.999975PPS2.434500e-050.0000241.000000e-09
52019-05-25 16:51:24.999973PPS2.658800e-050.0000271.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

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

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

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

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

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

can110

2019/07/10 07:18

報告のみ。以下の当方環境では正常に動作します。提示コードに問題はなさそうです。 Win10 Python 3.5.5 |Anaconda custom (64-bit)| (default, Apr 7 2018, 04:52:34) [MSC v.1900 64 bit (AMD64)] on win32 pandas:0.23.0 コンソール上で実行
Higomon

2019/07/10 08:14

ご検証、ありがとうござます。 お使いの環境だと正常動作するのですね。。。 Pandasではなく、Numpyの話ですが、先日取得したAnaconda(Anaconda3-2019.03)で Numpyのimportが出来ず、悪戦苦闘しました。 以下のサイトを参考に、Numpyのimport問題は解決しましたが、 上記Pandasの問題は解決に至っていません。 https://teratail.com/questions/149566 取り急ぎ、お礼申し上げます。
guest

回答2

0

ベストアンサー

コードの詳細内容は把握していませんが、***部分を修正することにより動作しました。

Python

1# 略 2 3def main(): 4 f = open(path, mode='rt') 5 6# /// 前処理 /// 7 #列名の取得 8 header = [] 9 get_Header(f, header) 10 11 #ファイルボディの取得 12 body = [] 13 get_Body(f, body) 14 15 f.close() 16 17 #List --> Pandas DataFrameに変換 18 df = pd.DataFrame(body, dtype=float) 19 df.columns = header[0] #columnsの指定 ***2重リストになっているので[0]を渡す 20 21 print(df.columns) 22 print(df.head()) 23 24 #Cast 25 df['Date Time(UTC)'] = pd.to_datetime(df['Date Time(UTC)']) # ***最後の「,」を除く 26 df['Raw offset'] = df['Disp.'].astype(float)

投稿2019/07/12 07:34

can110

総合スコア38233

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

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

Higomon

2019/07/12 07:40

早急にバグを見つけて頂き、誠にありがとうございました。 感動しました!
guest

0

-コメントを受けて-

一応、自分が状況再現に用いたコードを載せておきます。これがうまく動作するかどうかも試してもらえると、回答時の参考になります。

python

1import pandas as pd 2import datetime 3 4##logf.logの中身(メモ帳で作ってlog拡張子で保存) 5 6#Date Time(UTC),Refid,Raw offset,Cooked offset,Disp. 7#2019-05-25 16:51:22.999972,PPSx,2.73E-05,0.000027,1.00E-09 8#2019-05-25 16:51:22.323771,NMEA,-3.24E-01,0.176228,1.00E-03 9#2019-05-25 16:51:23.999975,PPS,2.43E-05,0.000024,1.00E-09 10#2019-05-25 16:51:23.999975,PPSx,2.43E-05,0.000024,1.00E-09 11#2019-05-25 16:51:23.324379,NMEA,-3.24E-01,0.175621,1.00E-03 12#2019-05-25 16:51:24.999973,PPS,2.66E-05,0.000027,1.00E-09 13#2019-05-25 16:51:24.999973,PPSx,2.66E-05,0.000027,1.00E-09 14 15#logファイルの読み込み 16df=pd.read_csv('logf.log') 17 18#読み込み時点ではDate Time(UTC)のdtypeがobjectなのでdatetime64[ns]に変える 19df['Date Time(UTC)']=pd.to_datetime(df['Date Time(UTC)']) 20 21#データ抽出(どちらのコードでもうまくいった) 22df[df['Refid'] == 'PPS'] 23df.query("Refid == 'PPS'")

試したこと2について、以下のように修正した場合はどうでしょう。
※コードにミスが有ったので修正しました。

python

1#修正前 2df.query('Refid' == 'PPS') 3 4#修正後(等式全体を””で囲み、'Refid'をRefidに変える) 5df.query("Refid == 'PPS'")

参考:note.nkmk.me - pandas.DataFrameの行を条件で抽出するquery

投稿2019/07/10 12:53

編集2019/07/12 03:12
amahara_waya

総合スコア1029

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

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

Higomon

2019/07/11 02:48 編集

ご提案、ありがとうございます。 df.query("Refid == 'PPS'")を試しましたが、以下のエラーを吐いています。 #1 質問時とは異なり、環境をAnaconda → Minicondaとしましたが、  インストールしたPythonおよびPandasのバージョンは変更してません。  質問したPandas問題も未解決のままです。 #2 列名 Refidは設定しているはずですが、   下記最下部のError: name 'Refid' is not definedの意味が理解できてません。 --- KeyError Traceback (most recent call last) ~\Miniconda3\lib\site-packages\pandas\core\computation\scope.py in resolve(self, key, is_local) 180 if self.has_resolvers: --> 181 return self.resolvers[key] 182 ~\Miniconda3\lib\collections\__init__.py in __getitem__(self, key) 913 pass --> 914 return self.__missing__(key) # support subclasses that define __missing__ 915 ~\Miniconda3\lib\collections\__init__.py in __missing__(self, key) 905 def __missing__(self, key): --> 906 raise KeyError(key) 907 KeyError: 'Refid' During handling of the above exception, another exception occurred: KeyError Traceback (most recent call last) ~\Miniconda3\lib\site-packages\pandas\core\computation\scope.py in resolve(self, key, is_local) 191 # e.g., df[df > 0] --> 192 return self.temps[key] 193 except KeyError: KeyError: 'Refid' During handling of the above exception, another exception occurred: UndefinedVariableError Traceback (most recent call last) <ipython-input-3-f108e38e0600> in <module> ----> 1 df.query("Refid == 'PPS'") ~\Miniconda3\lib\site-packages\pandas\core\frame.py in query(self, expr, inplace, **kwargs) 3086 kwargs['level'] = kwargs.pop('level', 0) + 1 3087 kwargs['target'] = None -> 3088 res = self.eval(expr, **kwargs) 3089 3090 try: ~\Miniconda3\lib\site-packages\pandas\core\frame.py in eval(self, expr, inplace, **kwargs) 3201 kwargs['target'] = self 3202 kwargs['resolvers'] = kwargs.get('resolvers', ()) + tuple(resolvers) -> 3203 return _eval(expr, inplace=inplace, **kwargs) 3204 3205 def select_dtypes(self, include=None, exclude=None): ~\Miniconda3\lib\site-packages\pandas\core\computation\eval.py in eval(expr, parser, engine, truediv, local_dict, global_dict, resolvers, level, target, inplace) 292 293 parsed_expr = Expr(expr, engine=engine, parser=parser, env=env, --> 294 truediv=truediv) 295 296 # construct the engine and evaluate the parsed expression ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in __init__(self, expr, engine, parser, env, truediv, level) 747 self.env.scope['truediv'] = truediv 748 self._visitor = _parsers[parser](self.env, self.engine, self.parser) --> 749 self.terms = self.parse() 750 751 @property ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in parse(self) 764 def parse(self): 765 """Parse an expression""" --> 766 return self._visitor.visit(self.expr) 767 768 @property ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs) 329 method = 'visit_' + node.__class__.__name__ 330 visitor = getattr(self, method) --> 331 return visitor(node, **kwargs) 332 333 def visit_Module(self, node, **kwargs): ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Module(self, node, **kwargs) 335 raise SyntaxError('only a single expression is allowed') 336 expr = node.body[0] --> 337 return self.visit(expr, **kwargs) 338 339 def visit_Expr(self, node, **kwargs): ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs) 329 method = 'visit_' + node.__class__.__name__ 330 visitor = getattr(self, method) --> 331 return visitor(node, **kwargs) 332 333 def visit_Module(self, node, **kwargs): ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Expr(self, node, **kwargs) 338 339 def visit_Expr(self, node, **kwargs): --> 340 return self.visit(node.value, **kwargs) 341 342 def _rewrite_membership_op(self, node, left, right): ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs) 329 method = 'visit_' + node.__class__.__name__ 330 visitor = getattr(self, method) --> 331 return visitor(node, **kwargs) 332 333 def visit_Module(self, node, **kwargs): ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Compare(self, node, **kwargs) 664 op = self.translate_In(ops[0]) 665 binop = ast.BinOp(op=op, left=node.left, right=comps[0]) --> 666 return self.visit(binop) 667 668 # recursive case: we have a chained comparison, a CMP b CMP c, etc. ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs) 329 method = 'visit_' + node.__class__.__name__ 330 visitor = getattr(self, method) --> 331 return visitor(node, **kwargs) 332 333 def visit_Module(self, node, **kwargs): ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit_BinOp(self, node, **kwargs) 433 434 def visit_BinOp(self, node, **kwargs): --> 435 op, op_class, left, right = self._maybe_transform_eq_ne(node) 436 left, right = self._maybe_downcast_constants(left, right) 437 return self._maybe_evaluate_binop(op, op_class, left, right) ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in _maybe_transform_eq_ne(self, node, left, right) 370 def _maybe_transform_eq_ne(self, node, left=None, right=None): 371 if left is None: --> 372 left = self.visit(node.left, side='left') 373 if right is None: 374 right = self.visit(node.right, side='right') ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs) 329 method = 'visit_' + node.__class__.__name__ 330 visitor = getattr(self, method) --> 331 return visitor(node, **kwargs) 332 333 def visit_Module(self, node, **kwargs): ~\Miniconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Name(self, node, **kwargs) 447 448 def visit_Name(self, node, **kwargs): --> 449 return self.term_type(node.id, self.env, **kwargs) 450 451 def visit_NameConstant(self, node, **kwargs): ~\Miniconda3\lib\site-packages\pandas\core\computation\ops.py in __init__(self, name, env, side, encoding) 62 self.is_local = (tname.startswith(_LOCAL_TAG) or 63 tname in _DEFAULT_GLOBALS) ---> 64 self._value = self._resolve_name() 65 self.encoding = encoding 66 ~\Miniconda3\lib\site-packages\pandas\core\computation\ops.py in _resolve_name(self) 79 80 def _resolve_name(self): ---> 81 res = self.env.resolve(self.local_name, is_local=self.is_local) 82 self.update(res) 83 ~\Miniconda3\lib\site-packages\pandas\core\computation\scope.py in resolve(self, key, is_local) 192 return self.temps[key] 193 except KeyError: --> 194 raise compu.ops.UndefinedVariableError(key, is_local) 195 196 def swapkey(self, old_key, new_key, new_value=None): UndefinedVariableError: name 'Refid' is not defined
amahara_waya

2019/07/12 03:00

質問にある表をもとに作ったdataframeを使った場合では問題なく動作したので、入力ファイル(logファイル)の問題かもしれません。 ※環境はPython: 3.7.1, Pandas: 0.23.4,Jupyter Notebook logファイル自体もしくはファイルの中身(コンマのついたテキスト形式になっているはず)を提示できないでしょうか。
Higomon

2019/07/12 07:21

ご丁寧に検証頂き、ありがとうございます。 質問の簡単化のため記載しておりませんでしたが、 logファイル(original)と前処理も含めたPython codeすべてを記載しました。 改めてご参照くださいませ。 PythonのバージョンやOSを変えても正常に動かないので、前処理部分がおかしいはずですが、 恥ずかしながら、経験不足のため、何がおかしいのか未だ発見できていません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問