-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcmd_message.py
More file actions
354 lines (290 loc) · 12.4 KB
/
Copy pathcmd_message.py
File metadata and controls
354 lines (290 loc) · 12.4 KB
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
import MeCab
from wordcloud import WordCloud
import collections
import csv as c
from tqdm import tqdm
import seaborn as sns
import matplotlib.pyplot as plt
import re
def _mecab_wakati(text):
# 形態素解析を行う(分かち書き)
wakati_tagger = MeCab.Tagger("-Owakati") # 分かち書き
parse = wakati_tagger.parse(text)
return parse
def _mecab(text):
# 形態素解析を行い品詞リストを返す
tagger = MeCab.Tagger()
tagger.parse("")
node = tagger.parseToNode(text)
node_list = []
while node:
# 例: ['吾輩', '名詞', '代名詞', '一般', '*', '*', '*', '吾輩', 'ワガハイ', 'ワガハイ']
node_list.append([node.surface]+node.feature.split(","))
node = node.next
node_list = node_list[1:-1] # BOS/EOSタグを除外
return node_list
# キーワード解析
def keyword_analy(text):
key_out = []
key_list = ["ように", "修正", "追加", "削除", "作成", "設定", "保存",
"変更", "編集", "更新", "整理", "調整", "実装", "表示", "化"]
for key in key_list:
if key in text:
key_out.append(key)
return key_out
class WordCloudGenerator:
"""
WordCloud
"""
out_file_name = ""
def __init__(self, font_path, background_color, width, height, collocations,
stopwords, max_words, regexp):
"""
出力パラメータ初期化
"""
self.font_path = font_path
self.background_color = background_color
self.width = width
self.height = height
self.collocations = collocations
self.stopwords = stopwords
self.max_words = max_words
self.regexp = regexp
def wordcloud_draw(self, parse):
"""
wordcloud画像を出力
@param
parse 形態素解析結果
"""
self.wordcloud = WordCloud(font_path=self.font_path, background_color=self.background_color, width=self.width, height=self.height,
collocations=self.collocations, stopwords=self.stopwords, max_words=self.max_words, regexp=self.regexp, repeat=False)
self.wordcloud.generate(parse)
self.wordcloud.to_file(self.out_file_name)
def frequency_count(self, wakati_text):
"""
単語の頻出頻度算出
@param
wakati_text str 分かち書きテキスト
"""
words = wakati_text.split(" ")
words = [word for word in words if word not in self.stopwords]
word_freq = collections.Counter(words)
return word_freq
def frequency_count_jp(self, wakati_text):
"""
日本語の単語頻出頻度算出
@param
wakati_text str 分かち書きテキスト
"""
words = wakati_text.split(" ")
compile_words = re.compile('[!"#$%&\'\\\\()*+,-./:;<=>?@[\\]^_`{|}~「」〔〕“”〈〉『』【】&*・()$#@。、?!`+¥%]')
compile_abc_123 = re.compile(r'[a-zA-Z0-90-9]')
words_jp = []
for word in words:
if not bool(compile_words.search(word)):
if not bool(compile_abc_123.search(word)):
words_jp.append(word)
word_freq = collections.Counter(words_jp)
return word_freq
def _get_all_commit_message(repo):
"""
すべてのcommit messageを取得する
"""
all_commit_message = ""
with open("log/eliminate_message.txt", "w", encoding="utf-8") as f:
for commit in repo.iter_commits():
# Mergeから始まるcommit messageは除外
if not commit.message.startswith('Merge'):
all_commit_message += commit.message
try:
f.write(commit.author)
except TypeError:
pass
f.write(","+commit.message+"\n")
return all_commit_message
def _get_commit_message_by_author(repo, author):
"""
指定したauthorのcommit messageを取得する
"""
commit_message = ""
for commit in repo.iter_commits():
if commit.author == author:
# Mergeから始まるcommit messageは除外
if not commit.message.startswith('Merge'):
commit_message += commit.message
return commit_message
def _wordcloud_all_messages(repo, wordCloudGenerator):
"""
すべてのcommit messageでwordcloudを作成する
"""
# 入力テキストファイル
OUT_FILE_NAME = "pic/wordcloud_message.png"
# 形態素解析
text = _get_all_commit_message(repo)
mecab_all = _mecab(text) # 形態素解析
# 名詞及び名詞連結を取得#
"""
名詞連結は,現状うまく動かないので,一旦コメントアウト
"""
# mecab_linking_noun = []
# for m in range(len(mecab_all)-1):
# if mecab_all[m][1] == "名詞" and mecab_all[m+1][1] == "名詞":
# mecab_linking_noun.append(
# mecab_all[m][0]+mecab_all[m+1][0])
# elif mecab_all[m][1] == "名詞":
# mecab_linking_noun.append(mecab_all[m][0])
# else:
# pass
mecab_only_noun = [m[0] for m in mecab_all if m[1] == "名詞"] # 名詞のみ取得
wakati = " ".join(mecab_only_noun) # 分かち書き
wordCloudGenerator.out_file_name = OUT_FILE_NAME # 出力ファイル名
wordCloudGenerator.wordcloud_draw(wakati) # 出力
print(f"{wordCloudGenerator.out_file_name}に画像を出力しました")
print()
def _wordcloud_by_author(repo, wordCloudGenerator):
"""
authorごとにwordcloudを作成する
"""
# 入力テキストファイル
OUT_FILE_NAME = "pic/wordcloud_message_author/{}.png"
# すべてのauthorを取得 #この方法はちょっと時間がかかるかも.最適化の余地あり.
authors = set()
for commit in repo.iter_commits():
authors.add(commit.author)
# 各authorのcommit messageを取得
authors_text = dict()
for author in authors:
# authorの名前は一緒だが,メアドが違う場合があるとき,同じauthorとみなしてmessageを結合する
if author.name in authors_text:
authors_text[author.name] += _get_commit_message_by_author(
repo, author)
else:
authors_text[author.name] = _get_commit_message_by_author(
repo, author)
for author, text in authors_text.items():
# 形態素解析
mecab_all = _mecab(text) # 形態素解析
# リストが空の場合はスキップ
if len(mecab_all) == 0:
continue
# 名詞及び名詞連結を取得#
"""
名詞連結は,現状うまく動かないので,一旦コメントアウト
"""
# mecab_linking_noun = []
# for m in range(len(mecab_all)-1):
# if mecab_all[m][1] == "名詞" and mecab_all[m+1][1] == "名詞":
# mecab_linking_noun.append(
# mecab_all[m][0]+mecab_all[m+1][0])
# elif mecab_all[m][1] == "名詞":
# mecab_linking_noun.append(mecab_all[m][0])
# else:
# pass
mecab_only_noun = [m[0] for m in mecab_all if m[1] == "名詞"] # 名詞のみ取得
wakati = " ".join(mecab_only_noun) # 分かち書き
wordCloudGenerator.out_file_name = OUT_FILE_NAME.format(author) # 出力ファイル名
wordCloudGenerator.wordcloud_draw(wakati) # 出力
print(f"{wordCloudGenerator.out_file_name}に画像を出力しました")
print("すべてのcontributorのwordcloudを出力しました")
print()
def run(repo):
# message.csv
f = open("./log/message.csv", "w+", encoding="utf_8_sig", newline='')
csv = c.writer(f)
# csvヘッダー追加
csv.writerow([
'commit_no',
'message',
'len',
'key_flag',
'keyword',
'marp_flag'
'morpheme'])
sum_commits = repo.git.rev_list('--count', 'HEAD') # コミットの総数
commit_count = 0
sum_message_len = 0 # メッセージの文字数合計
key_match_count = 0 # キーワードの一致回数合計
# commit message を取得
with tqdm(total=int(sum_commits), desc='message.csv') as pbar: # プログレスバーの設定
for commit in repo.iter_commits():
commit_no = int(sum_commits) - commit_count
message_len = int(len(commit.message)) - 1
sum_message_len += message_len
keyword = keyword_analy(commit.message)
key_flag = len(keyword)
if key_flag == 0:
keyword = "none"
else:
key_match_count += 1
# message.csvに書き込み
csv.writerow([
commit_no,
commit.message,
message_len,
key_flag,
keyword,
0,
"none"])
commit_count += 1
pbar.update(1) # プログレスバーの進捗率を更新
"""
wordcloud生成処理
"""
#### パラメータ ####
STOP_WORDS = [" ", " "] # ストップワード
MAX_WORDS = 2000 # 出力個数の上限
WIDTH = 500 # 出力画像の幅
HEIGHT = 500 # 出力画像の高さ
FONT_FILE = "font/ipaexg.ttf" # フォントファイルのパス
wordCloudGenerator = WordCloudGenerator(font_path=FONT_FILE, background_color="white", width=WIDTH, height=HEIGHT, collocations=False,
stopwords=STOP_WORDS, max_words=MAX_WORDS, regexp=r"[\w']+") # WordCloud初期化
_wordcloud_by_author(repo, wordCloudGenerator) # authorごとにwordcloudを作成
# _wordcloud_all_messages(repo, wordCloudGenerator) # 全メッセージをwordcloudにして出力
# 単語の頻出頻度
wordCloudGenerator.out_file_name = "./pic/word_frequency.png"
"""マージ前の処理と同じはず"""
mecab_all = _mecab(_get_all_commit_message(repo)) # 形態素解析
mecab_only_noun = [m[0] for m in mecab_all if m[1] == "名詞"] # 名詞のみ取得
wakati = " ".join(mecab_only_noun) # 分かち書き
frequency_words = wordCloudGenerator.frequency_count_jp(wakati).most_common(30)
sns.set(context="talk", font='Yu Gothic')
fig = plt.subplots(figsize=(18, 8))
sns.countplot(y=mecab_only_noun, order=[i[0] for i in frequency_words])
plt.subplots_adjust(left=0.175, right=0.95, bottom=0.12, top=0.95)
plt.savefig("pic/frequency_words.png")
print("pic/frequency_words.pngに画像を出力しました")
print("---メッセージ解析結果---")
print("総メッセージ数:" + sum_commits)
print("文字数の平均:{:.1f}".format(sum_message_len/int(sum_commits)))
print("キーワード一致回数:" + str(key_match_count))
print()
f.close()
if __name__ == "__main__":
OUT_FILE_NAME = "pic/wordcloud_message.png"
TEXT = "吾輩は吾輩である.名前はスーパー吾輩である.Yes, I am wagahai."
mecab_all = _mecab(TEXT) # 形態素解析
# 名詞及び名詞連結を取得#
"""
名詞連結は,現状うまく動かないので,一旦コメントアウト
"""
# mecab_linking_noun = []
# for m in range(len(mecab_all)-1):
# if mecab_all[m][1] == "名詞" and mecab_all[m+1][1] == "名詞":
# mecab_linking_noun.append(
# mecab_all[m][0]+mecab_all[m+1][0])
# elif mecab_all[m][1] == "名詞":
# mecab_linking_noun.append(mecab_all[m][0])
# else:
# pass
mecab_only_noun = [m[0] for m in mecab_all if m[1] == "名詞"] # 名詞のみ取得
#### パラメータ ####
STOP_WORDS = [" "] # ストップワード
MAX_WORDS = 2000 # 出力個数の上限
WIDTH = 500 # 出力画像の幅
HEIGHT = 500 # 出力画像の高さ
FONT_FILE = "data/ipaexg.ttf" # フォントファイルのパス
wakati = " ".join(mecab_only_noun) # 分かち書き
wordCloudGenerator = WordCloudGenerator(font_path=FONT_FILE, background_color="white", width=WIDTH, height=HEIGHT, collocations=False,
stopwords=STOP_WORDS, max_words=MAX_WORDS, regexp=r"[\w']+") # WordCloud初期化
wordCloudGenerator.out_file_name = OUT_FILE_NAME # 出力ファイル名
wordCloudGenerator.wordcloud_draw(wakati) # 出力