著者:飯尾淳
本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温かく見守ってください。皆さんと共に勉強していきましょう。第1回は、アンケート結果から非定型なデータを取り出して集計します。
シェルスクリプトマガジン Vol.71は以下のリンク先でご購入できます。![]()
![]()
図5 形態素解析の処理をするPythonコード
#!/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コード
#!/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コード
#!/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()