閲覧いただきありがとうございます。
python3でコーディングしており、2種類の区切り('|'と':')文字で構成されたレコードを分割し、分類コードを付与してレコードをグループ分けしようと考えています。
下記にデータイメージを記載します。最初に、'|'でパースして要素を分けて、「品物」という項目と「グループ」という項目に対して、分類コードを付与します。「品物」と「グループ」の分類コードが一致している場合は同一レコードに出力して、異なる場合は別レコードとして出力したいです。
※ソースを記載しました。データイメージと記述内容が異なっていますが、読み替えてくれると助かります。
やりたいことは、愚直にfor文で分類分けしているロジックをもっと効率する方法はないか。
現状だと数万件のデータが来たらかなり遅い処理になると予想しているので改善したいのです。
大変恐縮ですが、アドバイスいただけると助かります。
###データイメージ
【項目名】'注文No' | '品物' | 'グループ'
注文001 | みかん:りんご:ピーマン | くだもの:やさい
注文002 | みかん:レシート |
注文003 | | くだもの:やさい
注文004 | ピーマン:レタス| やさい:たべもの
###理想の結果イメージ
【項目名】
'注文No','品物','グループ','分類コード'
注文001,みかん:りんご ,くだもの,1
注文001,ピーマン ,やさい ,2
注文002,みかん , ,1
注文002,領収書 , ,99
注文003, ,くだもの,1
注文003, ,やさい ,2
注文004,ピーマン:レタス,やさい:たべもの,2
###ソース
pyhon3
1def logDistribution(value): 2 """ 3 ログ分類処理 4 :param value: チェック対象の文字列 5 """ 6 # dos 7 chk = re.match(r"^IPBLOCK-*", value) 8 if chk: 9 return '4' 10 11 # bot manager 12 chk = re.match(r"^39", value) 13 if chk: 14 return '2' 15 chk = re.match(r"^BOT-", value) 16 if chk: 17 return '2' 18 19 # client reputation 20 chk = re.match(r"^REP_", value) 21 if chk: 22 return '3' 23 24 # API Protection 25 chk = re.match(r"^API_", value) 26 if chk: 27 return '6' 28 29 # UA filter 30 chk = re.match(r"^6", value) 31 if chk: 32 return '7' 33 34 # no match 35 return '1' 36 37def log_parser(): 38 test_file = 'C:\tmp/sample_apache_log.txt' 39 40 reader = pd.read_csv(test_file, sep='\n', chunksize=50,header=None) 41 for row in reader: 42 regex = '([(\d.)]+) - - [(.*?)] "(\S+?)(?: +(.*?) +(\S*?))?" (\d+) (\d+) "(.*?)" "(.*?)" "(.*?)" "(.*?)"' 43 44 pd_result=row[0].str.extract(regex, expand=True) 45 # 46 print(pd_result.at[0,0]) 47 print(pd_result.at[0,1]) 48 print(pd_result.at[0,2]) 49 print(pd_result.at[0,3]) 50 print(pd_result.at[0,4]) 51 print(pd_result.at[0,5]) 52 print(pd_result.at[0,6]) 53 print(pd_result.at[0,7]) 54 print(pd_result.at[0,8]) 55 print(pd_result.at[0,9]) 56 print(pd_result.at[0,10]) #分類分けデータ 57 58 # policyID,ruleID,riskName 59 pd_result[[11,12,13]] = pd_result[10].str.split('|', expand=True) 60 61 # 複数カラムにまたがる処理を愚直にforでやってる(todo:改善したい) 62 for i, row in pd_result.iterrows(): 63 64 log_kind = 0 # init 65 if row[12] == [''] and row[13] == [''] : 66 log_kind = 5 # Access_log 67 print (row[10] + 'is :' +log_kind) 68 #pd_result.at[i, 14] = log_kind # ★★要デバッグ 69 continue 70 71 # RuleID 72 ruleID = row[12].split(':') 73 ruleID_dir = [] 74 75 if ruleID == ['']: 76 pass 77 else : 78 for rID in ruleID: 79 log_code = logDistribution(str(rID)) 80 ruleID_dir += [log_code] 81 82 # Risk Group Name 83 riskName = row[13].split(':') 84 riskName_dir = [] 85 86 if riskName == ['']: 87 pass 88 else: 89 for rName in riskName: 90 log_code = logDistribution(str(rName)) 91 riskName_dir += [log_code] 92 93 # ログの分割 94 Aggregation_dir = [] 95 if not ruleID_dir: 96 pass 97 else: 98 for i in range(len(ruleID_dir)): 99 tmp_dir = [ruleID_dir[i],ruleID[i],'',row[11]] 100 if i == 0: 101 Aggregation_dir.append(tmp_dir) 102 else : 103 # すでにAggregation_dirに登録されてる分類コードなら:で連結する 104 merge_flg = False 105 for j in range(len(Aggregation_dir)): 106 if Aggregation_dir[j][0] == tmp_dir[0]: 107 if not Aggregation_dir[j][1]: 108 Aggregation_dir[j][1] = tmp_dir[1] 109 merge_flg = True 110 else: 111 Aggregation_dir[j][1] = Aggregation_dir[j][1] + ':' + tmp_dir[1] 112 merge_flg = True 113 if merge_flg == False : 114 Aggregation_dir.append(tmp_dir) 115 if not riskName_dir: 116 pass 117 else: 118 for i in range(len(riskName_dir)): 119 tmp_dir = [riskName_dir[i],'',riskName[i],row[11]] 120 if i == 0 and not Aggregation_dir: 121 Aggregation_dir.append(tmp_dir) 122 else : 123 # すでにAggregation_dirに登録されてる分類コードなら:で連結する 124 merge_flg = False 125 for j in range(len(Aggregation_dir)): 126 if Aggregation_dir[j][0] == tmp_dir[0]: 127 if not Aggregation_dir[j][2]: 128 Aggregation_dir[j][2] = tmp_dir[2] 129 merge_flg = True 130 else: 131 Aggregation_dir[j][2] = Aggregation_dir[j][2] + ':' + tmp_dir[2] 132 merge_flg = True 133 if merge_flg == False : 134 Aggregation_dir.append(tmp_dir) 135 print(Aggregation_dir) 136 137 # Aggregation_dirで増えたレコードをもとのpandasに追加 138 139 140 141if __name__ == "__main__": 142 # ログをファイルから読み込み 143 log_parser() 144 145
あなたの回答
tips
プレビュー