Connected to Python 3.13.7
In [ ]:
import pandas as pd
import re
from pathlib import Path
from fugashi import Tagger # type: ignore
import unicodedata
from sudachipy import Dictionary, SplitMode
tokenizer = Dictionary().create()
tagger = Tagger('-Owakati')
def cleanse_text_all(text: str) -> str:
"""root_to_text()した後のテキストを正規化する。
1.nfkc
2.記号の一部を大文字に揃える
3.~~数字を0にする~~
4.連続する空白を削除する (改行は残す、空白を完全に削除しないほうがよさげ)
"""
def cleanse_normalise(text: str) -> str:
"""文字列の正規化
まず、記号とかをすべて半角にした後、それっぽいものは全角にする。
(全角にする意味ある? 全角のやつがnfkc適用されずに残っているときある。)
ただし、数字と空白以外"""
text = unicodedata.normalize("NFKC", text)
# いくつかの文字を全角にする。nfkcしているから半角への変換はいらんと思う。
tostr = "!”#$%’()*+,-./:=?@[¥]^_`{|};〜。、・「」"
fromstr = "!\"#$%\'()*+,-./:=?@[¥]^_`{|};~。、・「」"
pt = re.compile('([{}]+)'.format(fromstr))
text = text.translate(text.maketrans(fromstr, tostr)) if pt.search(text) else text
return text
def cleanse_number(text: str, zero_all=False) -> str:
"""text (string) の前処理
zero_all: true: 数字をすべて0にする、連続する0を一つの0にする
covid-19とかiso14000とかも巻き込まれる。0に置換しない方が形態素解析がうまくいくかも
単位区切りの,.は削除してもいい。sudachipyなら問題ないが、fugashiなら区切られてしまう。
"""
if zero_all:
# 連続数字を0に
text = re.sub(r"\d+", "0", text)
# 桁区切り、小数点のある数字を0に
text = re.sub(r"0[,.]0", "0", text)
else:
# 桁区切り、小数点を削除
text = re.sub(r"(\d)[,.](\d)", r"\1\2", text)
return text
def cleanse_space(text: str) -> str:
"""textの前処理
連続する空白を削除する。
"""
text = text.replace(" ", " ")
# # [^\S\n]は改行以外の空白
text = re.sub(r"[^\S\n]+", " ", text)
return text
text = cleanse_normalise(text)
text = cleanse_number(text)
text = cleanse_space(text)
return text
In [ ]:
data_dir = Path("../_data")
vtt_files = sorted(data_dir.glob("*.vtt"))
rows = []
for vtt_file in vtt_files:
text = vtt_file.read_text(encoding="utf-8")
# VTTブロックを正規表現でパース
pattern = re.compile(
r"(\d{2}:\d{2}:\d{2}\.\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2}\.\d{3})\n(.+)"
)
for m in pattern.finditer(text):
start, end, content = m.group(1), m.group(2), m.group(3).strip()
# 「発話者: 発言内容」の形式を分離
if ": " in content:
speaker, utterance = content.split(": ", 1)
else:
speaker, utterance = "", content
rows.append({
"file_name": vtt_file.name,
"start_time": start,
"end_time": end,
"speaker": speaker,
"text": utterance,
})
df = pd.DataFrame(rows)
print(f"全{len(df)}行, ファイル数: {df['file_name'].nunique()}")
df.head(2)
全1911行, ファイル数: 2
Out[ ]:
| file_name | start_time | end_time | speaker | text | |
|---|---|---|---|---|---|
| 0 | GMT20260217-234927_v2.vtt | 00:06:20.650 | 00:06:21.809 | カワイ | 戻るんですか? |
| 1 | GMT20260217-234927_v2.vtt | 00:10:10.460 | 00:10:14.739 | 天王寺 | おはようございます。今秋田さん入られます。お待ちください。 |
In [ ]:
df.value_counts("speaker")
Out[ ]:
speaker 砂糖 368 橋本 277 スズキ 175 平山 126 山下 124 下川 107 カワイ 99 井上 95 上西 92 西野 78 野村 53 村田 50 淀屋橋 45 所沢 43 沢井 43 本町 40 なんば 28 日本橋 28 天王寺 19 夕日 16 昭和 5 Name: count, dtype: int64
In [ ]:
def wakati(text, pos_filter=None):
"""
textを分かち書きする
pos_filter: 文字列 ("名詞") なら単一品詞、リスト (["名詞", "助詞"]) なら複数品詞を残す。Noneなら全て残す。
"""
# # fugashi
# return [word for word in tagger(text)]
# # sudachi
# morphemes = tokenizer.tokenize(text, SplitMode.C)
if pos_filter is None:
return [m.dictionary_form() for m in tokenizer.tokenize(text, SplitMode.C)]
if isinstance(pos_filter, str):
pos_filter = [pos_filter]
return [m.dictionary_form() for m in tokenizer.tokenize(text, SplitMode.C) if m.part_of_speech()[0] in pos_filter]
In [ ]:
# ! text列を分かち書きする
df["wakati"] = df["text"].apply(wakati)
# df["wakati"] = df["text"].apply(lambda x: wakati(x, "名詞"))
In [ ]:
# ! とりあえず一人だけ取り出して
tmp = df.loc[df["speaker"] == "砂糖"]
In [ ]:
word_counts = tmp["wakati"].explode().value_counts()
word_counts.head(20)
Out[ ]:
wakati 、 369 。 329 と 221 の 193 か 191 だ 180 ます 157 て 140 で 127 です 126 って 106 は 106 する 105 た 100 も 99 に 94 が 93 いう 92 ? 82 てる 73 Name: count, dtype: int64
In [ ]:
# ! text列をtokenizeしてpart_of_speech()の6要素を列に展開する
def tokenize_pos(text):
morphemes = tokenizer.tokenize(text, SplitMode.C)
return [(m.dictionary_form(), *m.part_of_speech()) for m in morphemes]
POS_COLUMNS = ["品詞", "品詞細分類1", "品詞細分類2", "品詞細分類3", "活用型", "活用形"]
df["pos_list"] = df["text"].apply(tokenize_pos)
# 全話者版 (補助記号のみ除外、長さ制限なし): 助詞・感動詞の分析に使う
df_all = df.explode("pos_list").reset_index(drop=True)
df_all[["dic_form"] + POS_COLUMNS] = pd.DataFrame(
df_all["pos_list"].tolist(), index=df_all.index
)
df_all = df_all.drop(columns=["pos_list", "wakati", "text"])
df_all["len"] = df_all["dic_form"].str.len()
df_all = df_all.loc[df_all["品詞"] != "補助記号"]
# 砂糖さん単独版 (既存フィルタそのまま)
df_morphemes = df.loc[df["speaker"] == "砂糖"]
df_morphemes = df_morphemes.explode("pos_list").reset_index(drop=True)
df_morphemes[["dic_form"] + POS_COLUMNS] = pd.DataFrame(
df_morphemes["pos_list"].tolist(), index=df_morphemes.index
)
df_morphemes = df_morphemes.drop(columns=["pos_list", "wakati", "text"])
df_morphemes["len"] = df_morphemes["dic_form"].str.len()
# ? filter
# # 補助記号 (。)、接頭辞 (3つくらいしかない)、一文字、です、ます、する
df_morphemes = df_morphemes.loc[-df_morphemes["品詞"].str.contains("補助記号|接頭")]
df_morphemes = df_morphemes.loc[df_morphemes["len"] >= 2]
df_morphemes.head()
Out[ ]:
| file_name | start_time | end_time | speaker | dic_form | 品詞 | 品詞細分類1 | 品詞細分類2 | 品詞細分類3 | 活用型 | 活用形 | len | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | GMT20260218-044829_v2.vtt | 00:11:58.950 | 00:12:00.310 | 砂糖 | お疲れ様 | 名詞 | 普通名詞 | 形状詞可能 | * | * | * | 4 |
| 1 | GMT20260218-044829_v2.vtt | 00:11:58.950 | 00:12:00.310 | 砂糖 | です | 助動詞 | * | * | * | 助動詞-デス | 終止形-一般 | 2 |
| 3 | GMT20260218-044829_v2.vtt | 00:12:00.580 | 00:12:02.569 | 砂糖 | あれ | 代名詞 | * | * | * | * | * | 2 |
| 4 | GMT20260218-044829_v2.vtt | 00:12:00.580 | 00:12:02.569 | 砂糖 | 聞こえる | 動詞 | 一般 | * | * | 下一段-ア行 | 連用形-一般 | 4 |
| 5 | GMT20260218-044829_v2.vtt | 00:12:00.580 | 00:12:02.569 | 砂糖 | てる | 助動詞 | * | * | * | 下一段-タ行 | 連用形-一般 | 2 |
In [ ]:
df_morphemes["品詞"].value_counts()
# 前処理前
# 助詞 12718
# 名詞 8530
# 動詞 5724
# 補助記号 5558
# 助動詞 5192
# 副詞 2291
# 感動詞 2039
# 連体詞 856
# 代名詞 741
# 形容詞 702
# 接尾辞 626
# 接頭辞 318
# 形状詞 315
# 接続詞 293
# 記号 2
Out[ ]:
品詞 名詞 853 動詞 788 助動詞 435 副詞 277 助詞 275 感動詞 218 代名詞 113 形容詞 105 連体詞 104 接尾辞 63 形状詞 46 接続詞 30 Name: count, dtype: int64
In [ ]:
# ! 頻出単語
min_df = 0.001
max_df = 0.20
df_docs = pd.DataFrame(df_morphemes.value_counts("dic_form")).reset_index()
df_docs["proportion"] = df_docs["count"] / df_docs.shape[0]
df_docs.loc[
(df_docs["proportion"] >= min_df) &
(df_docs["proportion"] <= max_df)
]
Out[ ]:
| dic_form | count | proportion | |
|---|---|---|---|
| 1 | です | 126 | 0.175732 |
| 2 | って | 106 | 0.147838 |
| 3 | する | 105 | 0.146444 |
| 4 | いう | 92 | 0.128312 |
| 5 | てる | 73 | 0.101813 |
| ... | ... | ... | ... |
| 712 | 木札 | 1 | 0.001395 |
| 713 | そろそろ | 1 | 0.001395 |
| 714 | ばええ | 1 | 0.001395 |
| 715 | 内容 | 1 | 0.001395 |
| 716 | しか | 1 | 0.001395 |
716 rows × 3 columns
In [ ]:
# ============================================================
# ! 話者ごとの言葉遣いの違いを3側面で見る
# (A) 話題の違い: 内容語 Top-N
# (B) 文体の違い: 助詞・助動詞の使用率
# (C) フィラー/相槌: 感動詞
# ============================================================
# 主要話者 (形態素数 上位) を抽出
top_speakers = (
df_all.groupby("speaker").size()
.sort_values(ascending=False).head(6).index.tolist()
)
print(top_speakers)
['橋本', '砂糖', 'カワイ', '下川', '平山', 'スズキ']
In [ ]:
def _hms_to_sec(t):
h, m, s = t.split(":")
return int(h) * 3600 + int(m) * 60 + float(s)
df["duration_sec"] = df["end_time"].map(_hms_to_sec) - df["start_time"].map(_hms_to_sec)
speaker_summary = pd.DataFrame({
"発話回数": df.groupby("speaker").size(),
"発話時間_秒": df.groupby("speaker")["duration_sec"].sum().round(1),
"形態素数": df_all.groupby("speaker").size(),
})
speaker_summary["形態素/分"] = (
speaker_summary["形態素数"] / speaker_summary["発話時間_秒"] * 60
).round(1)
speaker_summary["形態素/回"] = (
speaker_summary["形態素数"] / speaker_summary["発話回数"]
).round(1)
speaker_summary = speaker_summary.sort_values("形態素数", ascending=False)
# 正規化の分母 (話者の総形態素数)
speaker_totals = df_all.groupby("speaker").size()
speaker_summary.reset_index()
Out[ ]:
| speaker | 発話回数 | 発話時間_秒 | 形態素数 | 形態素/分 | 形態素/回 | |
|---|---|---|---|---|---|---|
| 0 | 橋本 | 277 | 2185.9 | 7168 | 196.8 | 25.9 |
| 1 | 砂糖 | 368 | 1638.7 | 5558 | 203.5 | 15.1 |
| 2 | カワイ | 99 | 994.5 | 3539 | 213.5 | 35.7 |
| 3 | 下川 | 107 | 1008.3 | 3452 | 205.4 | 32.3 |
| 4 | 平山 | 126 | 767.8 | 2611 | 204.0 | 20.7 |
| 5 | スズキ | 175 | 781.1 | 2528 | 194.2 | 14.4 |
| 6 | 山下 | 124 | 764.8 | 2460 | 193.0 | 19.8 |
| 7 | 西野 | 78 | 611.5 | 2098 | 205.9 | 26.9 |
| 8 | 上西 | 92 | 457.5 | 1607 | 210.8 | 17.5 |
| 9 | 井上 | 95 | 389.9 | 1332 | 205.0 | 14.0 |
| 10 | 所沢 | 43 | 347.1 | 1232 | 213.0 | 28.7 |
| 11 | 村田 | 50 | 394.4 | 1080 | 164.3 | 21.6 |
| 12 | 本町 | 40 | 209.0 | 957 | 274.7 | 23.9 |
| 13 | 野村 | 53 | 336.3 | 951 | 169.7 | 17.9 |
| 14 | 日本橋 | 28 | 275.2 | 865 | 188.6 | 30.9 |
| 15 | 淀屋橋 | 45 | 219.3 | 755 | 206.6 | 16.8 |
| 16 | 沢井 | 43 | 215.5 | 641 | 178.5 | 14.9 |
| 17 | 夕日 | 16 | 164.0 | 577 | 211.1 | 36.1 |
| 18 | なんば | 28 | 177.8 | 540 | 182.2 | 19.3 |
| 19 | 天王寺 | 19 | 100.4 | 311 | 185.9 | 16.4 |
| 20 | 昭和 | 5 | 35.8 | 85 | 142.5 | 17.0 |
In [ ]:
def top_words_by_speaker(df, speakers, pos=None, n=15, min_len=2, stopwords=None):
"""話者 × 頻出語 Top-N の横並び表。
pos=None で絞らず、pos='名詞' 等で品詞1種に絞る。
stopwords: 除外する dic_form の集合。None なら除外しない。
"""
d = df[df["speaker"].isin(speakers)]
if pos is not None:
d = d[d["品詞"] == pos]
if min_len:
d = d[d["dic_form"].str.len() >= min_len]
if stopwords:
d = d[~d["dic_form"].isin(stopwords)]
out = {}
for sp in speakers:
vc = d.loc[d["speaker"] == sp, "dic_form"].value_counts().head(n)
out[sp] = vc.reset_index().apply(
lambda r: f"{r['dic_form']} ({r['count']})", axis=1
)
return pd.concat(out, axis=1)
def top_words_rate_by_speaker(df, speakers, totals, pos=None, n=15, min_len=2, stopwords=None):
"""Top-N を "word (X.XX‰)" で表示。
‰ = 話者の総形態素数 (totals[speaker]) に対する千分率 = 発話量コントロール後の出現率。
件数ランクと同じ順位 (話者内で単調変換) だが、値が比率なので話者間で直接比較できる。
stopwords: 除外する dic_form の集合。None なら除外しない。
"""
d = df[df["speaker"].isin(speakers)]
if pos is not None:
d = d[d["品詞"] == pos]
if min_len:
d = d[d["dic_form"].str.len() >= min_len]
if stopwords:
d = d[~d["dic_form"].isin(stopwords)]
out = {}
for sp in speakers:
vc = d.loc[d["speaker"] == sp, "dic_form"].value_counts().head(n)
rate = vc / totals[sp] * 1000
out[sp] = pd.Series(
[f"{w} ({r:.2f}‰)" for w, r in zip(vc.index, rate.values)],
name=sp,
)
return pd.concat(out, axis=1)
def usage_rate_by_speaker(df, speakers, pos, top_k=20, stopwords=None):
"""話者 × dic_form の使用率 (%) 表。
その話者の pos 総数に対する割合として正規化。
stopwords: 除外する dic_form の集合。None なら除外しない。
"""
d = df[(df["speaker"].isin(speakers)) & (df["品詞"] == pos)]
if stopwords:
d = d[~d["dic_form"].isin(stopwords)]
tab = (
d.groupby(["speaker", "dic_form"]).size()
.groupby(level=0).apply(lambda s: s / s.sum() * 100)
.droplevel(0)
.unstack("speaker", fill_value=0)
)
tab = tab.loc[tab.sum(axis=1).sort_values(ascending=False).head(top_k).index]
return tab.round(2)
In [ ]:
stopwords = {
"する", "ます", "です"
}
# 以下、各Top-Nは 件数版と‰版の2種類を出す
# 件数版: たくさん話す情報を残す。
# ‰版: 話者の総形態素数で割って、発話量コントロール後の比較。
In [ ]:
top_words_by_speaker(df_all, top_speakers, pos=None, n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | ええ (249) | って (106) | えー (131) | えー (129) | ええ (54) | いう (53) |
| 1 | あの (123) | いう (92) | いう (79) | いう (68) | てる (46) | ない (52) |
| 2 | いう (108) | てる (73) | あの (48) | って (47) | まあ (44) | って (42) |
| 3 | ない (106) | さん (57) | ええ (46) | ない (46) | いう (40) | てる (33) |
| 4 | って (98) | はい (54) | ない (39) | ところ (40) | ある (31) | こと (23) |
| 5 | てる (92) | ない (54) | って (39) | ある (36) | あの (29) | ちょっと (21) |
| 6 | まあ (91) | あの (50) | ところ (33) | こと (31) | ない (27) | もう (20) |
| 7 | ある (69) | えっと (46) | ちょっと (32) | てる (29) | ちょっと (26) | やる (18) |
| 8 | こう (65) | けど (42) | なる (31) | やっぱり (27) | って (21) | ある (17) |
| 9 | ちょっと (63) | ある (42) | ある (31) | から (26) | けれど (20) | 思う (16) |
| 10 | 思う (61) | ちょっと (40) | てる (31) | たり (23) | 思う (20) | けど (16) |
| 11 | けれど (58) | どう (38) | けど (25) | いる (19) | えっと (19) | アクションプラン (16) |
| 12 | そう (52) | これ (38) | けれど (23) | ちょっと (19) | そう (19) | あの (15) |
| 13 | なる (49) | 思う (36) | まあ (21) | そこ (19) | はい (18) | これ (14) |
| 14 | さん (39) | ところ (35) | 思う (21) | えっと (18) | たり (18) | いい (13) |
In [ ]:
top_words_rate_by_speaker(df_all, top_speakers, speaker_totals, pos=None, n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | ええ (34.74‰) | って (19.07‰) | えー (37.02‰) | えー (37.37‰) | ええ (20.68‰) | いう (20.97‰) |
| 1 | あの (17.16‰) | いう (16.55‰) | いう (22.32‰) | いう (19.70‰) | てる (17.62‰) | ない (20.57‰) |
| 2 | いう (15.07‰) | てる (13.13‰) | あの (13.56‰) | って (13.62‰) | まあ (16.85‰) | って (16.61‰) |
| 3 | ない (14.79‰) | さん (10.26‰) | ええ (13.00‰) | ない (13.33‰) | いう (15.32‰) | てる (13.05‰) |
| 4 | って (13.67‰) | はい (9.72‰) | ない (11.02‰) | ところ (11.59‰) | ある (11.87‰) | こと (9.10‰) |
| 5 | てる (12.83‰) | ない (9.72‰) | って (11.02‰) | ある (10.43‰) | あの (11.11‰) | ちょっと (8.31‰) |
| 6 | まあ (12.70‰) | あの (9.00‰) | ところ (9.32‰) | こと (8.98‰) | ない (10.34‰) | もう (7.91‰) |
| 7 | ある (9.63‰) | えっと (8.28‰) | ちょっと (9.04‰) | てる (8.40‰) | ちょっと (9.96‰) | やる (7.12‰) |
| 8 | こう (9.07‰) | けど (7.56‰) | なる (8.76‰) | やっぱり (7.82‰) | って (8.04‰) | ある (6.72‰) |
| 9 | ちょっと (8.79‰) | ある (7.56‰) | ある (8.76‰) | から (7.53‰) | けれど (7.66‰) | 思う (6.33‰) |
| 10 | 思う (8.51‰) | ちょっと (7.20‰) | てる (8.76‰) | たり (6.66‰) | 思う (7.66‰) | けど (6.33‰) |
| 11 | けれど (8.09‰) | どう (6.84‰) | けど (7.06‰) | いる (5.50‰) | えっと (7.28‰) | アクションプラン (6.33‰) |
| 12 | そう (7.25‰) | これ (6.84‰) | けれど (6.50‰) | ちょっと (5.50‰) | そう (7.28‰) | あの (5.93‰) |
| 13 | なる (6.84‰) | 思う (6.48‰) | まあ (5.93‰) | そこ (5.50‰) | はい (6.89‰) | これ (5.54‰) |
| 14 | さん (5.44‰) | ところ (6.30‰) | 思う (5.93‰) | えっと (5.21‰) | たり (6.89‰) | いい (5.14‰) |
In [ ]:
top_words_by_speaker(df_all, top_speakers, pos="名詞", n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | こと (27) | ところ (35) | ところ (33) | ところ (40) | こと (9) | こと (23) |
| 1 | あと (23) | こと (30) | こと (19) | こと (31) | お客様 (7) | アクションプラン (16) |
| 2 | 一回 (13) | お客さん (16) | 一応 (10) | 感じ (9) | 単価 (6) | もの (12) |
| 3 | もの (13) | 本店 (14) | 本店 (8) | もの (9) | 売り上げ (5) | 具体的 (7) |
| 4 | 本店 (12) | 店長 (12) | 業者 (6) | 共有 (9) | 客数 (5) | 問題 (7) |
| 5 | ところ (11) | 店舗 (11) | もの (6) | パック (7) | 切手 (5) | メニュー (6) |
| 6 | 売り上げ (10) | あと (11) | 白山 (5) | ふう (6) | 年間 (5) | とんかつ (6) |
| 7 | 店舗 (10) | 商品 (10) | ふう (5) | 主任 (6) | 原価 (4) | 改善 (6) |
| 8 | お客様 (9) | ごめん (9) | あと (5) | 全体 (6) | ところ (4) | ところ (5) |
| 9 | 集客 (9) | 状況 (9) | 管理 (5) | 灰皿 (6) | 北山 (4) | 現場 (5) |
| 10 | 清水 (8) | 売り上げ (9) | スタッフ (5) | オペレーション (5) | 一度 (4) | 声がけ (4) |
| 11 | 意見 (8) | 部長 (9) | お客様 (5) | 基本的 (5) | 感じ (4) | スタッフ (4) |
| 12 | みんな (7) | 一応 (8) | 課題 (5) | あと (5) | 仕入れ (3) | 一回 (4) |
| 13 | 先ほど (7) | さん付け (8) | トイレ (5) | 目標 (5) | 来店 (3) | 職人 (4) |
| 14 | スタッフ (7) | 渡辺 (7) | 一回 (5) | 今月 (5) | 平均 (3) | 部分 (4) |
In [ ]:
top_words_rate_by_speaker(df_all, top_speakers, speaker_totals, pos="名詞", n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | こと (3.77‰) | ところ (6.30‰) | ところ (9.32‰) | ところ (11.59‰) | こと (3.45‰) | こと (9.10‰) |
| 1 | あと (3.21‰) | こと (5.40‰) | こと (5.37‰) | こと (8.98‰) | お客様 (2.68‰) | アクションプラン (6.33‰) |
| 2 | 一回 (1.81‰) | お客さん (2.88‰) | 一応 (2.83‰) | 感じ (2.61‰) | 単価 (2.30‰) | もの (4.75‰) |
| 3 | もの (1.81‰) | 本店 (2.52‰) | 本店 (2.26‰) | もの (2.61‰) | 売り上げ (1.91‰) | 具体的 (2.77‰) |
| 4 | 本店 (1.67‰) | 店長 (2.16‰) | 業者 (1.70‰) | 共有 (2.61‰) | 客数 (1.91‰) | 問題 (2.77‰) |
| 5 | ところ (1.53‰) | 店舗 (1.98‰) | もの (1.70‰) | パック (2.03‰) | 切手 (1.91‰) | メニュー (2.37‰) |
| 6 | 売り上げ (1.40‰) | あと (1.98‰) | 白山 (1.41‰) | ふう (1.74‰) | 年間 (1.91‰) | とんかつ (2.37‰) |
| 7 | 店舗 (1.40‰) | 商品 (1.80‰) | ふう (1.41‰) | 主任 (1.74‰) | 原価 (1.53‰) | 改善 (2.37‰) |
| 8 | お客様 (1.26‰) | ごめん (1.62‰) | あと (1.41‰) | 全体 (1.74‰) | ところ (1.53‰) | ところ (1.98‰) |
| 9 | 集客 (1.26‰) | 状況 (1.62‰) | 管理 (1.41‰) | 灰皿 (1.74‰) | 北山 (1.53‰) | 現場 (1.98‰) |
| 10 | 清水 (1.12‰) | 売り上げ (1.62‰) | スタッフ (1.41‰) | オペレーション (1.45‰) | 一度 (1.53‰) | 声がけ (1.58‰) |
| 11 | 意見 (1.12‰) | 部長 (1.62‰) | お客様 (1.41‰) | 基本的 (1.45‰) | 感じ (1.53‰) | スタッフ (1.58‰) |
| 12 | みんな (0.98‰) | 一応 (1.44‰) | 課題 (1.41‰) | あと (1.45‰) | 仕入れ (1.15‰) | 一回 (1.58‰) |
| 13 | 先ほど (0.98‰) | さん付け (1.44‰) | トイレ (1.41‰) | 目標 (1.45‰) | 来店 (1.15‰) | 職人 (1.58‰) |
| 14 | スタッフ (0.98‰) | 渡辺 (1.26‰) | 一回 (1.41‰) | 今月 (1.45‰) | 平均 (1.15‰) | 部分 (1.58‰) |
In [ ]:
top_words_by_speaker(df_all, top_speakers, pos="動詞", n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | いう (108) | いう (92) | いう (79) | いう (68) | いう (40) | いう (53) |
| 1 | ある (65) | ある (42) | なる (31) | ある (35) | ある (30) | やる (18) |
| 2 | 思う (61) | 思う (36) | ある (29) | いる (19) | 思う (20) | ある (16) |
| 3 | なる (49) | なる (30) | 思う (21) | やる (13) | いく (14) | 思う (16) |
| 4 | いく (38) | 願う (26) | いる (19) | なる (13) | いただく (13) | 言う (12) |
| 5 | おる (27) | やる (24) | いただく (15) | 言う (9) | おる (12) | いく (10) |
| 6 | やる (26) | 思る (23) | できる (13) | いく (9) | やる (12) | 思る (10) |
| 7 | 願う (21) | ござる (21) | 来る (11) | 行く (8) | なる (11) | なる (10) |
| 8 | いただく (19) | いる (19) | いく (10) | おる (8) | できる (10) | 出す (9) |
| 9 | 思る (17) | 行く (16) | やる (10) | よる (7) | 関する (9) | くる (9) |
| 10 | ござる (16) | いく (15) | 願う (8) | 思う (7) | もらう (9) | いただく (7) |
| 11 | くる (16) | 見る (15) | 思る (8) | できる (7) | いる (7) | わかる (7) |
| 12 | できる (15) | 言う (14) | 使う (8) | くる (6) | ござる (6) | 出る (7) |
| 13 | いる (14) | 上がる (12) | わかる (8) | 出す (5) | くる (6) | できる (6) |
| 14 | 言う (13) | いただく (11) | いただける (8) | 来る (5) | 言う (6) | 回す (6) |
In [ ]:
top_words_rate_by_speaker(df_all, top_speakers, speaker_totals, pos="動詞", n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | いう (15.07‰) | いう (16.55‰) | いう (22.32‰) | いう (19.70‰) | いう (15.32‰) | いう (20.97‰) |
| 1 | ある (9.07‰) | ある (7.56‰) | なる (8.76‰) | ある (10.14‰) | ある (11.49‰) | やる (7.12‰) |
| 2 | 思う (8.51‰) | 思う (6.48‰) | ある (8.19‰) | いる (5.50‰) | 思う (7.66‰) | ある (6.33‰) |
| 3 | なる (6.84‰) | なる (5.40‰) | 思う (5.93‰) | やる (3.77‰) | いく (5.36‰) | 思う (6.33‰) |
| 4 | いく (5.30‰) | 願う (4.68‰) | いる (5.37‰) | なる (3.77‰) | いただく (4.98‰) | 言う (4.75‰) |
| 5 | おる (3.77‰) | やる (4.32‰) | いただく (4.24‰) | 言う (2.61‰) | おる (4.60‰) | いく (3.96‰) |
| 6 | やる (3.63‰) | 思る (4.14‰) | できる (3.67‰) | いく (2.61‰) | やる (4.60‰) | 思る (3.96‰) |
| 7 | 願う (2.93‰) | ござる (3.78‰) | 来る (3.11‰) | 行く (2.32‰) | なる (4.21‰) | なる (3.96‰) |
| 8 | いただく (2.65‰) | いる (3.42‰) | いく (2.83‰) | おる (2.32‰) | できる (3.83‰) | 出す (3.56‰) |
| 9 | 思る (2.37‰) | 行く (2.88‰) | やる (2.83‰) | よる (2.03‰) | 関する (3.45‰) | くる (3.56‰) |
| 10 | ござる (2.23‰) | いく (2.70‰) | 願う (2.26‰) | 思う (2.03‰) | もらう (3.45‰) | いただく (2.77‰) |
| 11 | くる (2.23‰) | 見る (2.70‰) | 思る (2.26‰) | できる (2.03‰) | いる (2.68‰) | わかる (2.77‰) |
| 12 | できる (2.09‰) | 言う (2.52‰) | 使う (2.26‰) | くる (1.74‰) | ござる (2.30‰) | 出る (2.77‰) |
| 13 | いる (1.95‰) | 上がる (2.16‰) | わかる (2.26‰) | 出す (1.45‰) | くる (2.30‰) | できる (2.37‰) |
| 14 | 言う (1.81‰) | いただく (1.98‰) | いただける (2.26‰) | 来る (1.45‰) | 言う (2.30‰) | 回す (2.37‰) |
In [ ]:
top_words_by_speaker(df_all, top_speakers, pos="形容詞", n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | ない (50) | ない (33) | ない (14) | ない (25) | ない (8) | ない (16) |
| 1 | ええ (41) | いい (31) | いい (9) | いい (6) | ええ (6) | いい (13) |
| 2 | いい (12) | よろしい (8) | 多い (5) | すごい (6) | すごい (4) | ほしい (6) |
| 3 | 多い (5) | 多い (5) | ええ (4) | 多い (4) | いい (3) | 美味しい (1) |
| 4 | すごい (3) | 難しい (4) | 高い (4) | ええ (4) | 少ない (2) | すごい (1) |
| 5 | よろしい (3) | すごい (4) | 難しい (3) | 少ない (2) | 多い (2) | ええ (1) |
| 6 | 寂しい (3) | ほしい (3) | 大きい (1) | 大きい (2) | 低い (1) | ものすごい (1) |
| 7 | 新しい (2) | うまい (2) | 遅い (1) | おいしい (2) | 新しい (1) | 新しい (1) |
| 8 | 高い (2) | ええ (2) | おかしい (1) | 早い (2) | ほしい (1) | 限りない (1) |
| 9 | 悪い (2) | 長い (2) | 欲しい (1) | 若い (1) | 細かい (1) | 近い (1) |
| 10 | 硬い (2) | 高い (2) | 早い (1) | 遅い (1) | 嬉しい (1) | 悪い (1) |
| 11 | 正しい (1) | 良い (2) | すごい (1) | 忙しい (1) | 厳しい (1) | 少ない (1) |
| 12 | 目新しい (1) | 少ない (1) | 四角い (1) | 深い (1) | NaN | 辛い (1) |
| 13 | 細かい (1) | よい (1) | 悪い (1) | 高い (1) | NaN | NaN |
| 14 | 欲しい (1) | 小さい (1) | 面白い (1) | はええ (1) | NaN | NaN |
In [ ]:
top_words_rate_by_speaker(df_all, top_speakers, speaker_totals, pos="形容詞", n=15, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | ない (6.98‰) | ない (5.94‰) | ない (3.96‰) | ない (7.24‰) | ない (3.06‰) | ない (6.33‰) |
| 1 | ええ (5.72‰) | いい (5.58‰) | いい (2.54‰) | いい (1.74‰) | ええ (2.30‰) | いい (5.14‰) |
| 2 | いい (1.67‰) | よろしい (1.44‰) | 多い (1.41‰) | すごい (1.74‰) | すごい (1.53‰) | ほしい (2.37‰) |
| 3 | 多い (0.70‰) | 多い (0.90‰) | ええ (1.13‰) | 多い (1.16‰) | いい (1.15‰) | 美味しい (0.40‰) |
| 4 | すごい (0.42‰) | 難しい (0.72‰) | 高い (1.13‰) | ええ (1.16‰) | 少ない (0.77‰) | すごい (0.40‰) |
| 5 | よろしい (0.42‰) | すごい (0.72‰) | 難しい (0.85‰) | 少ない (0.58‰) | 多い (0.77‰) | ええ (0.40‰) |
| 6 | 寂しい (0.42‰) | ほしい (0.54‰) | 大きい (0.28‰) | 大きい (0.58‰) | 低い (0.38‰) | ものすごい (0.40‰) |
| 7 | 新しい (0.28‰) | うまい (0.36‰) | 遅い (0.28‰) | おいしい (0.58‰) | 新しい (0.38‰) | 新しい (0.40‰) |
| 8 | 高い (0.28‰) | ええ (0.36‰) | おかしい (0.28‰) | 早い (0.58‰) | ほしい (0.38‰) | 限りない (0.40‰) |
| 9 | 悪い (0.28‰) | 長い (0.36‰) | 欲しい (0.28‰) | 若い (0.29‰) | 細かい (0.38‰) | 近い (0.40‰) |
| 10 | 硬い (0.28‰) | 高い (0.36‰) | 早い (0.28‰) | 遅い (0.29‰) | 嬉しい (0.38‰) | 悪い (0.40‰) |
| 11 | 正しい (0.14‰) | 良い (0.36‰) | すごい (0.28‰) | 忙しい (0.29‰) | 厳しい (0.38‰) | 少ない (0.40‰) |
| 12 | 目新しい (0.14‰) | 少ない (0.18‰) | 四角い (0.28‰) | 深い (0.29‰) | NaN | 辛い (0.40‰) |
| 13 | 細かい (0.14‰) | よい (0.18‰) | 悪い (0.28‰) | 高い (0.29‰) | NaN | NaN |
| 14 | 欲しい (0.14‰) | 小さい (0.18‰) | 面白い (0.28‰) | はええ (0.29‰) | NaN | NaN |
In [ ]:
usage_rate_by_speaker(df_all, top_speakers, pos="助詞", top_k=20, stopwords=stopwords)
Out[ ]:
| speaker | カワイ | スズキ | 下川 | 平山 | 橋本 | 砂糖 |
|---|---|---|---|---|---|---|
| dic_form | ||||||
| の | 12.01 | 12.00 | 15.30 | 13.54 | 11.58 | 10.97 |
| て | 12.90 | 12.48 | 7.65 | 13.18 | 14.47 | 7.96 |
| と | 10.16 | 11.02 | 11.87 | 9.31 | 8.82 | 12.56 |
| は | 8.92 | 6.49 | 9.94 | 5.20 | 5.93 | 6.03 |
| か | 5.92 | 6.49 | 5.72 | 6.77 | 6.29 | 10.86 |
| も | 9.63 | 6.24 | 3.78 | 6.05 | 8.82 | 5.63 |
| に | 5.12 | 6.73 | 7.30 | 6.89 | 6.38 | 5.34 |
| が | 4.33 | 5.51 | 8.18 | 6.05 | 4.04 | 5.29 |
| で | 6.10 | 5.02 | 4.84 | 3.87 | 5.79 | 6.03 |
| って | 3.45 | 5.02 | 4.13 | 2.54 | 4.50 | 6.03 |
| を | 2.56 | 5.75 | 5.63 | 3.99 | 3.26 | 2.50 |
| ん | 4.06 | 3.43 | 1.58 | 5.93 | 5.42 | 3.18 |
| ね | 1.50 | 1.35 | 1.76 | 1.69 | 1.93 | 3.52 |
| けど | 2.21 | 1.84 | 1.58 | 1.81 | 0.92 | 2.39 |
| な | 2.47 | 0.61 | 0.79 | 1.93 | 1.56 | 1.93 |
| から | 0.88 | 0.98 | 2.29 | 1.57 | 1.47 | 1.88 |
| けれど | 2.03 | 0.73 | 0.00 | 2.30 | 2.62 | 0.17 |
| たり | 0.71 | 0.24 | 2.02 | 2.18 | 0.83 | 1.14 |
| よ | 0.27 | 2.82 | 1.23 | 0.60 | 0.37 | 1.42 |
| ば | 1.24 | 0.98 | 0.09 | 0.36 | 0.83 | 0.80 |
In [ ]:
usage_rate_by_speaker(df_all, top_speakers, pos="助動詞", top_k=20, stopwords=stopwords)
Out[ ]:
| speaker | カワイ | スズキ | 下川 | 平山 | 橋本 | 砂糖 |
|---|---|---|---|---|---|---|
| dic_form | ||||||
| だ | 41.54 | 39.00 | 42.45 | 39.85 | 40.92 | 40.27 |
| た | 21.92 | 21.62 | 26.98 | 21.46 | 21.93 | 22.37 |
| てる | 11.92 | 12.74 | 10.43 | 17.62 | 15.06 | 16.33 |
| ない | 9.62 | 13.90 | 7.55 | 7.28 | 9.17 | 4.70 |
| たい | 3.46 | 3.86 | 1.44 | 4.98 | 3.11 | 3.58 |
| れる | 1.15 | 2.70 | 2.88 | 2.68 | 3.93 | 2.91 |
| ぬ | 2.69 | 2.70 | 0.72 | 0.38 | 1.15 | 1.34 |
| せる | 1.92 | 0.77 | 2.16 | 2.30 | 1.31 | 0.22 |
| られる | 1.54 | 0.00 | 0.36 | 1.15 | 0.16 | 0.45 |
| り | 0.38 | 0.00 | 1.08 | 1.15 | 0.82 | 0.00 |
| や | 0.00 | 1.16 | 0.00 | 0.00 | 0.16 | 1.34 |
| とる | 0.38 | 0.00 | 0.00 | 0.00 | 0.00 | 2.01 |
| てく | 0.00 | 0.39 | 0.36 | 0.00 | 0.00 | 1.57 |
| ず | 0.38 | 0.00 | 0.72 | 0.38 | 0.33 | 0.00 |
| む | 0.00 | 0.39 | 0.00 | 0.77 | 0.00 | 0.45 |
| けり | 0.00 | 0.00 | 0.00 | 0.00 | 1.15 | 0.22 |
| させる | 1.15 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
| てらっしゃる | 0.77 | 0.00 | 0.00 | 0.00 | 0.00 | 0.22 |
| き | 0.00 | 0.00 | 0.72 | 0.00 | 0.16 | 0.00 |
| てえ | 0.00 | 0.00 | 0.72 | 0.00 | 0.16 | 0.00 |
In [ ]:
top_words_by_speaker(df_all, top_speakers, pos="感動詞", n=15, min_len=0, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | ええ (208) | はい (54) | えー (131) | えー (129) | ええ (48) | えー (8) |
| 1 | え (99) | えっと (46) | ええ (42) | え (31) | え (46) | はい (6) |
| 2 | はい (22) | えー (33) | え (31) | えっと (18) | えっと (19) | あ (4) |
| 3 | あ (17) | えっ (32) | ま (24) | はい (15) | はい (18) | ええ (3) |
| 4 | ありがとう (10) | ありがとう (21) | はい (7) | えーとー (12) | えっ (7) | ええと (3) |
| 5 | ま (8) | あ (10) | あ (7) | えっ (12) | ありがとう (6) | え (3) |
| 6 | えー (7) | え (7) | えっ (6) | ええ (5) | いや (4) | えっと (3) |
| 7 | あの (6) | ええと (7) | えっと (4) | ありがとう (5) | えー (3) | ありがとう (1) |
| 8 | う (4) | えーと (6) | あのー (3) | えーと (4) | ええと (2) | さ (1) |
| 9 | まあ (4) | えっとー (5) | おー (2) | ま (4) | あ (2) | あのー (1) |
| 10 | ああ (3) | あれ (4) | うー (2) | まー (4) | ああ (2) | うー (1) |
| 11 | おはようございます (2) | ま (2) | んー (2) | えっとー (2) | ま (1) | いや (1) |
| 12 | えっと (2) | あっ (2) | あの (2) | あ (2) | えーと (1) | ええー (1) |
| 13 | へえ (2) | あのー (2) | う (1) | あー (2) | あの (1) | あー (1) |
| 14 | よし (1) | えーとー (1) | まー (1) | あの (2) | まあ (1) | えーと (1) |
In [ ]:
top_words_rate_by_speaker(df_all, top_speakers, speaker_totals, pos="感動詞", n=15, min_len=0, stopwords=stopwords)
Out[ ]:
| 橋本 | 砂糖 | カワイ | 下川 | 平山 | スズキ | |
|---|---|---|---|---|---|---|
| 0 | ええ (29.02‰) | はい (9.72‰) | えー (37.02‰) | えー (37.37‰) | ええ (18.38‰) | えー (3.16‰) |
| 1 | え (13.81‰) | えっと (8.28‰) | ええ (11.87‰) | え (8.98‰) | え (17.62‰) | はい (2.37‰) |
| 2 | はい (3.07‰) | えー (5.94‰) | え (8.76‰) | えっと (5.21‰) | えっと (7.28‰) | あ (1.58‰) |
| 3 | あ (2.37‰) | えっ (5.76‰) | ま (6.78‰) | はい (4.35‰) | はい (6.89‰) | ええ (1.19‰) |
| 4 | ありがとう (1.40‰) | ありがとう (3.78‰) | はい (1.98‰) | えーとー (3.48‰) | えっ (2.68‰) | ええと (1.19‰) |
| 5 | ま (1.12‰) | あ (1.80‰) | あ (1.98‰) | えっ (3.48‰) | ありがとう (2.30‰) | え (1.19‰) |
| 6 | えー (0.98‰) | え (1.26‰) | えっ (1.70‰) | ええ (1.45‰) | いや (1.53‰) | えっと (1.19‰) |
| 7 | あの (0.84‰) | ええと (1.26‰) | えっと (1.13‰) | ありがとう (1.45‰) | えー (1.15‰) | ありがとう (0.40‰) |
| 8 | う (0.56‰) | えーと (1.08‰) | あのー (0.85‰) | えーと (1.16‰) | ええと (0.77‰) | さ (0.40‰) |
| 9 | まあ (0.56‰) | えっとー (0.90‰) | おー (0.57‰) | ま (1.16‰) | あ (0.77‰) | あのー (0.40‰) |
| 10 | ああ (0.42‰) | あれ (0.72‰) | うー (0.57‰) | まー (1.16‰) | ああ (0.77‰) | うー (0.40‰) |
| 11 | おはようございます (0.28‰) | ま (0.36‰) | んー (0.57‰) | えっとー (0.58‰) | ま (0.38‰) | いや (0.40‰) |
| 12 | えっと (0.28‰) | あっ (0.36‰) | あの (0.57‰) | あ (0.58‰) | えーと (0.38‰) | ええー (0.40‰) |
| 13 | へえ (0.28‰) | あのー (0.36‰) | う (0.28‰) | あー (0.58‰) | あの (0.38‰) | あー (0.40‰) |
| 14 | よし (0.14‰) | えーとー (0.18‰) | まー (0.28‰) | あの (0.58‰) | まあ (0.38‰) | えーと (0.40‰) |
In [ ]:
usage_rate_by_speaker(df_all, top_speakers, pos="感動詞", top_k=15, stopwords=stopwords)
Out[ ]:
| speaker | カワイ | スズキ | 下川 | 平山 | 橋本 | 砂糖 |
|---|---|---|---|---|---|---|
| dic_form | ||||||
| えー | 49.06 | 20.0 | 50.19 | 1.85 | 1.72 | 13.87 |
| ええ | 15.73 | 7.5 | 1.95 | 29.63 | 51.23 | 0.42 |
| え | 11.61 | 7.5 | 12.06 | 28.40 | 24.38 | 2.94 |
| はい | 2.62 | 15.0 | 5.84 | 11.11 | 5.42 | 22.69 |
| えっと | 1.50 | 7.5 | 7.00 | 11.73 | 0.49 | 19.33 |
| えっ | 2.25 | 0.0 | 4.67 | 4.32 | 0.25 | 13.45 |
| あ | 2.62 | 10.0 | 0.78 | 1.23 | 4.19 | 4.20 |
| ありがとう | 0.37 | 2.5 | 1.95 | 3.70 | 2.46 | 8.82 |
| ま | 8.99 | 0.0 | 1.56 | 0.62 | 1.97 | 0.84 |
| ええと | 0.00 | 7.5 | 0.00 | 1.23 | 0.25 | 2.94 |
| えーと | 0.00 | 2.5 | 1.56 | 0.62 | 0.00 | 2.52 |
| いや | 0.00 | 2.5 | 0.39 | 2.47 | 0.00 | 0.42 |
| あのー | 1.12 | 2.5 | 0.39 | 0.00 | 0.25 | 0.84 |
| えーとー | 0.00 | 0.0 | 4.67 | 0.00 | 0.00 | 0.42 |
| あー | 0.37 | 2.5 | 0.78 | 0.62 | 0.00 | 0.42 |