はじめに
本記事では、Google Playのレビュー本文をもとに、日本語感情辞書を使ってポジティブ・ネガティブの傾向をスコアリングし、月次推移として可視化する方法を紹介します。
アップデート直後やイベント時に「好評」「不満」どちらが増えたかを可視化することで、ユーザーの反応をデータで把握できます。
前提:レビュー取得はデータ取得編、テキスト整形・ストップワード設定はテキスト分析編を参照。 本記事はローカルに保存済みのCSV(例:reviews_genshin_paged.csv
)を読み込みます。
0. 手法の概要
- 感情辞書ベースのスコアリング: ポジティブ/ネガティブ語を辞書と照合してスコア化。
- 月次集計: レビュー日付ごとにスコア平均を取り、時間変化を可視化。
- Plotly可視化: 折れ線グラフでポジ・ネガの比率や平均感情を確認。
1. セットアップ
pip install pandas janome plotly
import pandas as pd
import re, unicodedata
from janome.tokenizer import Tokenizer
import plotly.graph_objects as go
from datetime import datetime
# データ読み込み
df = pd.read_csv("reviews_genshin_paged.csv")
df = df.dropna(subset=["content", "score"]).copy()
# 投稿日(例: "2025-10-06T00:00:00Z" → 日付化)
df["at"] = pd.to_datetime(df["at"], errors="coerce")
df = df.dropna(subset=["at"])
df["month"] = df["at"].dt.to_period("M").astype(str)
# =============================
# 感情辞書の用意(簡易PN辞書)
# =============================
# 辞書例:ポジティブ +1, ネガティブ -1
sentiment_dict = {
"楽しい": 1, "面白い": 1, "最高": 1, "神": 1, "良い": 1, "快適": 1, "嬉しい": 1, "好き": 1,
"つまらない": -1, "最悪": -1, "ひどい": -1, "重い": -1, "バグ": -1, "遅い": -1, "落ちる": -1,
"残念": -1, "やばい": -1, "不具合": -1, "イライラ": -1
}
# =============================
# 形態素解析・正規化
# =============================
t = Tokenizer(wakati=False)
def normalize_text(text):
text = unicodedata.normalize("NFKC", str(text))
text = re.sub(r"http\S+|www\.\S+"," ", text)
text = re.sub(r"[^\wぁ-んァ-ン一-龥ー]", " ", text)
return text
def tokenize(text):
text = normalize_text(text)
toks = []
for token in t.tokenize(text):
base = token.base_form if token.base_form != "*" else token.surface
pos = token.part_of_speech.split(",")[0]
if pos in {"名詞","形容詞","動詞"}:
toks.append(base)
return toks
df["tokens"] = df["content"].map(tokenize)
# =============================
# 感情スコアの算出
# =============================
def sentiment_score(tokens):
s = 0
c = 0
for w in tokens:
if w in sentiment_dict:
s += sentiment_dict[w]
c += 1
return s / c if c > 0 else 0
df["sentiment"] = df["tokens"].map(sentiment_score)
print(df[["content","sentiment"]].head())
辞書は汎用的な例です。分析対象に応じて語彙を追加してください。特に「課金」「広告」「アップデート」などはポジ・ネガ両面があるため、文脈を確認しながら調整するのが実務的です。
2. 月次集計と可視化(Plotly)
# 月次平均スコア
monthly = df.groupby("month", as_index=False)["sentiment"].mean()
# ポジ率・ネガ率(0より上/下)
df["pos_flag"] = df["sentiment"] > 0
df["neg_flag"] = df["sentiment"] < 0
rate = df.groupby("month").agg(
pos_rate=("pos_flag","mean"),
neg_rate=("neg_flag","mean"),
avg_sent=("sentiment","mean"),
count=("sentiment","size")
).reset_index()
# ========== Plotlyグラフ ==========
fig = go.Figure()
fig.add_trace(go.Scatter(x=rate["month"], y=rate["pos_rate"], name="ポジ率", mode="lines+markers", line=dict(color="#2ca02c")))
fig.add_trace(go.Scatter(x=rate["month"], y=rate["neg_rate"], name="ネガ率", mode="lines+markers", line=dict(color="#d62728")))
fig.add_trace(go.Scatter(x=rate["month"], y=rate["avg_sent"], name="平均スコア", mode="lines", line=dict(color="#1f77b4", dash="dot")))
fig.update_layout(
title="Google Playレビュー感情スコア(月次推移)",
xaxis_title="年月",
yaxis_title="スコア(率)",
template="plotly_white",
height=700
)
fig.show()
fig.write_html("sentiment_monthly_trend.html", include_plotlyjs="cdn")
グラフでは、緑=ポジティブ率、赤=ネガティブ率、青=平均スコアを表示。イベントやアップデートの時期と重ねて見ると、反応の変化が明確に分かります。
3. 感情語の頻度上位を確認(確認用)
from collections import Counter
all_tokens = [w for toks in df["tokens"] for w in toks if w in sentiment_dict]
cnt = Counter(all_tokens)
print(pd.DataFrame(cnt.most_common(20), columns=["word","freq"]))
分析対象タイトルごとに、頻出する感情語を確認して辞書を拡張するのが精度改善の第一歩です。
注意:感情辞書とスコアの調整について
感情スコアは辞書に依存するため、初期状態では十分に正確でない場合があります。
特定のタイトルでは「課金」「広告」「イベント」などがポジ・ネガ両面の語として扱われるため、数回のチューニングを前提に辞書を更新していくのが現実的です。
# 例:ネガティブ寄りに扱いたい語を追加
sentiment_dict.update({"課金": -0.5, "広告": -0.3})
# ポジティブ寄りに扱いたい語を追加
sentiment_dict.update({"イベント": 0.4, "アップデート": 0.3})
意味のないワードや曖昧な表現が多い場合は、STOPWORDSリストに追加することで改善される場合があります。
まとめ
- 日本語感情辞書を用いてレビュー本文のポジ・ネガ傾向を可視化。
- Plotlyで月次推移を描くことで、アップデートやイベントの反応変化を定量的に把握。
- 感情辞書とSTOPWORDSを段階的に調整し、タイトルに合わせて精度を高める。
- 初回実行で完全な結果を求めず、継続的な更新を前提に分析を育てることが重要。
※感情スコアはレビュー内容の「傾向」を表す参考値です。ポジ・ネガ比率の上下動は参考指標として扱い、他の指標(レビュー件数や平均スコア)とあわせて確認しましょう。