著者:飯尾淳
本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温かく見守ってください。皆さんと共に勉強していきましょう。第1回は、アンケート結果から非定型なデータを取り出して集計します。
シェルスクリプトマガジン Vol.71は以下のリンク先でご購入できます。
図5 形態素解析の処理をするPythonコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#!/usr/bin/env python import spacy import sys nlp = spacy.load('ja_ginza') for line in sys.stdin: # 一行ずつ処理 for sent in nlp(line.strip()).sents: # 一文ずつに分解 for token in sent: # さらに文中のトークンごとに処理 # i:トークン番号, orth_:表層形, lemma_:基本形, # pos_:品詞(英語), tag_:品詞細分類(日本語) sys.stdout.write(f'{token.i}\t{token.orth_}\t{token.lemma_}\t' f'{token.pos_}\t{token.tag_}\n') sys.stdout.write('EOS\n') |
図7 名詞の連接処理と抽出をするPythonコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#!/usr/bin/env python import sys import re def sequence_gen(): sequence = [] for line in sys.stdin: if line == 'EOS\n': yield sequence sequence = [] continue word_info = line.strip().split('\t') pos = word_info[4].split('-') sequence.append({'surface': word_info[1], 'base': word_info[2], 'pos': pos[0]}) pattern = re.compile('N+') for seq in sequence_gen(): encode_str = ''.join('N' if w['pos'] in ('名詞') else '?' for w in seq) for m in pattern.finditer(encode_str): print(''.join(w['surface'] for w in seq[m.start():m.end()])) |
図9 データを分析してプロットするPythonコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#!/usr/bin/env python import sys import numpy as np import matplotlib.pyplot as plt from sklearn.decomposition import PCA import spacy from matplotlib import rcParams rcParams['font.family'] = 'sans-serif' rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meiryo', 'Takao', 'IPAexGothic', 'IPAPGothic', 'VL PGothic', 'Noto Sans CJK JP'] nlp = spacy.load('ja_ginza') with open(sys.argv[1]) as f: texts = [s.strip() for s in f.readlines()] vectors = [nlp(t).vector for t in texts] pca = PCA(n_components=2).fit(vectors) trans = pca.fit_transform(vectors) pc_ratio = pca.explained_variance_ratio_ plt.figure() plt.scatter(trans[:,0], trans[:,1]) i = 0 for txt in texts: plt.text(trans[i,0]+0.02, trans[i,1]-0.02, txt) i += 1 plt.hlines(0, min(trans[:,0]), max(trans[:,0]), linestyle='dashed', linewidth=1) plt.vlines(0, min(trans[:,1]), max(trans[:,1]), linestyle='dashed', linewidth=1) plt.xlabel('PC1 ('+str(round(pc_ratio[0]*100,2))+'%)') plt.ylabel('PC2 ('+str(round(pc_ratio[1]*100,2))+'%)') plt.tight_layout() plt.show() |