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

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

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

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

pandas

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

Q&A

解決済

1回答

425閲覧

pandasで行列を取り込んだあと、パースと特定行のコピー作業を行いたい

zenji0705

総合スコア69

Python 3.x

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

pandas

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

0グッド

0クリップ

投稿2020/05/12 01:22

閲覧いただきありがとうございます。

python3でファイルサイズの大きいデータを取り込んで理想とする行列に成形したいです。
容量の大きいデータを取り込むにはpandasが処理早いとの文献を読んだので、pandasを用いました。
やりたいことは、アパッチログ+独自項目があるtxtファイルを取り込んで、
・独自項目をパース
・パースされた項目に値があった場合はアパッチログ行+パースされた項目の行を追加
したいです。

###データイメージ(初期データ)
index 項目名1 項目名2
0 アパッチログA  AAA|XXX|YYY
1 アパッチログB  BBB||
2 アパッチログC  CCC||ZZZ

###独自項目をパース
index 項目名1 項目名2 項目名3 項目名4
0 アパッチログA  AAA    XXX     YYY
1 アパッチログB  BBB    NaN     NaN
2 アパッチログC  CCC    NaN     ZZZ

###パースされた場合は、アパッチログ行+パースされた項目の行を追加
index 項目名1 項目名2 項目名3 項目名4
0 アパッチログA  AAA    NaN     NaN
1 アパッチログA  XXX    NaN     NaN
2 アパッチログA  YYY    NaN     NaN
3 アパッチログB  BBB    NaN     NaN
4 アパッチログC  CCC    NaN     NaN
5 アパッチログC  ZZZ    NaN     NaN

実際のデータ件数は数万件ある想定です。
1件ずつチェックしてレコード追加すると処理時間がかかる、初めてpandasを使ったので
y軸に対して、項目3、項目4に値があったら、ログを複製する・・・みたいなことが
できるのではないかと調べていたのですが、わかりませんでした。

###試したこと
大したことしてないですが・・・・
def log_parser():
test_file = 'C:\akamai_data/ftp_log/alds0001/tmp/sample_apache_log.txt'

reader = pd.read_csv(test_file, sep='\n', chunksize=50,header=None) for row in reader: regex = '([(\d.)]+) - - [(.*?)] "(\S+?)(?: +(.*?) +(\S*?))?" (\d+) (\d+) "(.*?)" "(.*?)" "(.*?)" "(.*?)"'

    アパッチログをパースする
pd_result=row[0].str.extract(regex, expand=True)
結果の確認
print(pd_result.at[0,0])
print(pd_result.at[0,1])
print(pd_result.at[0,2])
print(pd_result.at[0,3])
print(pd_result.at[0,4])
print(pd_result.at[0,5])
print(pd_result.at[0,6])
print(pd_result.at[0,7])
print(pd_result.at[0,8])
print(pd_result.at[0,9])
print(pd_result.at[0,10]) ※独自項目が入ってる

変換用エリア pd_result[11] = pd_result[10] todo pd_result[11]をパースする todo パースされて値があった場合はアパッチログを複製して行追加

    

###補足情報(言語/FW/ツール等のバージョンなど) 開発言語 python 3.6.8 開発環境 Eclipse 2020-03(4.15)

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

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

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

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

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

meg_

2020/05/12 02:10

・コードは「コードの挿入」で記入してください。 ・”独自項目をパース”までは完成している、との認識で合ってますか?
zenji0705

2020/05/12 05:23

大変失礼しました。 今後はコードの挿入で質問を投稿させていただきます。 独自項目のパース自体はsplitで実装できましたが、元のpandasの行列にマージすることはできておりませんでした。
guest

回答1

0

ベストアンサー

順番に。

項目名2列の文字列を分割して列に分けるには Series.str.split() を使います。

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.split.html

Python

1tmp = df['項目名2'].str.split('|', expand=True) 2print(tmp) 3# 0 1 2 4#0 AAA XXX YYY 5#1 BBB 6#2 CCC ZZZ

ですので、第2形態にするには上記のデータフレームを元のデータフレームに結合するだけとなります。

Python

1df[['項目名2','項目名3','項目名4']] = df['項目名2'].str.split('|', expand=True) 2print(df) 3# 項目名1 項目名2 項目名3 項目名4 4#0 アパッチログA AAA XXX YYY 5#1 アパッチログB BBB 6#2 アパッチログC CCC ZZZ

項目名2列の文字列を分割した結果を列を行に展開するには、`DataFrame.stack()``を使います

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.stack.html

Python

1tmp = df['項目名2'].str.split('|', expand=True).stack() 2print(tmp) 3#0 0 AAA 4# 1 XXX 5# 2 YYY 6#1 0 BBB 7# 1 8# 2 9#2 0 CCC 10# 1 11# 2 ZZZ 12#dtype: object

上記の場合、空のセルはいらないので '' を NaN に変化しておくと stack()時に削除されます。
あと、2つ目のIndexも不要なのでこれも削除して

Python

1tmp = df['項目名2'].str.split('|', expand=True).replace('', np.nan).stack().reset_index(level=1, drop=True) 2print(tmp) 3#0 AAA 4#0 XXX 5#0 YYY 6#1 BBB 7#2 CCC 8#2 ZZZ 9#dtype: object

あとは、この結果を最初のDataFrameをDataFrame.merge()にて結合すると良いだけです。

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html

```Python`
df = df[['項目名1']].merge(tmp.rename('項目名2'), left_index=True, right_index=True)
print(df)

項目名1 項目名2

#0 アパッチログA AAA
#0 アパッチログA XXX
#0 アパッチログA YYY
#1 アパッチログB BBB
#2 アパッチログC CCC
#2 アパッチログC ZZZ

以上、まとめるとこうなります。 ```Python import pandas as pd import numpy as np df = pd.DataFrame([['アパッチログA','AAA|XXX|YYY'], ['アパッチログB','BBB||'], ['アパッチログC','CCC||ZZZ']], columns=['項目名1','項目名2']) tmp = df['項目名2'].str.split('|', expand=True).replace('', np.nan).stack().reset_index(level=1, drop=True) df = df[['項目名1']].merge(tmp.rename('項目名2'), left_index=True, right_index=True).reset_index(drop=True) print(df) # 項目名1 項目名2 #0 アパッチログA AAA #1 アパッチログA XXX #2 アパッチログA YYY #3 アパッチログB BBB #4 アパッチログC CCC #5 アパッチログC ZZZ

投稿2020/05/12 02:17

編集2020/05/12 02:25
magichan

総合スコア15898

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

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

zenji0705

2020/05/12 05:22

迅速なご回答ありがとうございました。おかげさまで想定結果を作ることができました。 助かりました。ベストアンサーをつけさせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問