COLUMN

お役立ち情報

口コミ分析、商品改善、CRM施策に役立つ考え方や活用ヒントを紹介します。

なぜ「口コミ分析ツールの中」だけでは足りないのか

レビュー分析ツールは、単体で使う限り「ネガティブなレビューが増えている」「この商品は評価4.2だ」といった事実を教えてくれます。しかしEC事業の現場で本当に知りたいのは、その先です。

  • ネガティブレビューが増えた月は、実際に返品率も上がっているのか
  • 評価が落ちた商品は、翌月の売上にどう影響したのか
  • 品質改善に投資すべきなのはどの商品か

これらの問いに答えるには、口コミデータと社内の基幹データを同じ場所で突き合わせる必要があります。レビュー分析ツールのUIを眺めているだけでは永遠に到達できない領域です。

本記事では、レビュー分析SaaS「KAIZODE」のAPIからレビューデータを取得し、Databricksのレイクハウス上で社内の売上・返品データとJOINして相関を可視化するまでを、実際に動かしながら解説します。Databricksは無償のFree Editionを使うため、クレジットカード登録なしで最後まで再現できます。

扱う題材:EC複数モールのレビューデータ
所要時間:30〜60分程度


全体構成 ― メダリオンアーキテクチャ

Databricksでデータを扱う際の定石が、メダリオンアーキテクチャと呼ばれる3層構造です。

役割本記事での内容
Bronzeソースから取り込んだ生データをそのまま保存KAIZODE APIから取得した生レビュー / 社内売上・返品データ
Silverクレンジング・型変換・集計を経た分析可能な状態日付パース済みレビュー、月次センチメント指標
Goldビジネス利用に最適化された統合データ月次センチメント × 売上・返品のJOIN済みテーブル

生データをそのまま残しつつ段階的に精製していく考え方で、「集計をやり直したくなったらBronzeから作り直せる」という再現性が最大のメリットです。この用語自体はDatabricks社が提唱したものですが、考え方は一般的なデータエンジニアリングのベストプラクティスとして広く定着しています。


全体図


STEP 1:Databricks Free Edition のセットアップ

Databricks Free Edition にアクセスし、アカウントを作成します。メールアドレスがあれば数分で完了し、クレジットカードの登録は不要です。

作成が完了するとワークスペースが自動でプロビジョニングされます。

Free Editionの位置づけ
Free Editionは学習・検証・プロトタイピングを目的としたプランです。商用利用は不可、SLAの提供もなく、長期間アクティビティがないアカウントは削除される可能性があります。本記事の内容も「PoC・技術検証」として捉えてください。本番運用には有償プランが必要です。

コンピュートの接続

Databricksでコードを実行するには、ノートブックにコンピュート(計算リソース)をアタッチする必要があります。Free Editionではサーバーレスコンピュートが利用でき、クラスタの事前起動は不要です。

ノートブックを開いた状態で、画面右上の接続メニューから「Serverless」を選ぶだけで接続されます。/


STEP 2:KAIZODE APIキーの準備

KAIZODEの管理画面からAPIキーを発行します。APIは以下の形式です。

  • ベースURLhttps://kaizode-v2.scorobo.ai/api/v1
  • 認証x-api-key ヘッダーにAPIキーを指定
  • 主要エンドポイント/analysis_themes/{analysis_theme_id}/reviews

分析テーマID(analysis_theme_id)は、KAIZODE上で作成した分析テーマの識別子です。管理画面のURLまたはAPIの一覧取得エンドポイントから確認できます。

ノートブックでのAPIキーの扱い

APIキーをコードに直接書き込むのは避けたいところです。Databricksのウィジェット機能を使うと、ノートブック上部に入力欄を表示して値を渡せます。

dbutils.widgets.text("kaizode_api_key", "", "KAIZODE APIキー")
dbutils.widgets.text("analysis_theme_id", "", "分析テーマID")

KAIZODE_API_KEY = dbutils.widgets.get("kaizode_api_key")
ANALYSIS_THEME_ID = dbutils.widgets.get("analysis_theme_id")
BASE_URL = "https://kaizode-v2.scorobo.ai/api/v1"

assert KAIZODE_API_KEY, "上部のウィジェットにKAIZODE APIキーを入力してください"

CATALOG = "workspace"
SCHEMA = "kaizode_demo"

spark.sql(f"CREATE SCHEMA IF NOT EXISTS {CATALOG}.{SCHEMA}")
spark.sql(f"USE {CATALOG}.{SCHEMA}")


STEP 3:Bronze層 ― レビューデータの取り込み

KAIZODE APIからレビューを全件取得し、Deltaテーブルとして保存します。レビュー件数が多い場合に備えてページネーションに対応させます。

import requests
import pandas as pd

def fetch_kaizode_reviews(theme_id: str, api_key: str) -> pd.DataFrame:
    """KAIZODE APIからレビューを全件取得(ページネーション対応)"""
    headers = {"x-api-key": api_key}
    all_reviews = []
    page = 0
    while True:
        resp = requests.get(
            f"{BASE_URL}/analysis_themes/{theme_id}/reviews",
            headers=headers,
            params={"limit": 500, "page": page},
            timeout=30,
        )
        resp.raise_for_status()
        payload = resp.json()
        reviews = payload.get("data", [])
        all_reviews.extend(reviews)

        pagination = payload.get("pagination", {})
        total_items = pagination.get("total_items", len(all_reviews))
        if len(all_reviews) >= total_items or not reviews:
            break
        page += 1

    return pd.DataFrame(all_reviews)

reviews_pdf = fetch_kaizode_reviews(ANALYSIS_THEME_ID, KAIZODE_API_KEY)
print(f"取得件数: {len(reviews_pdf)}")
display(reviews_pdf.head(10))

取得したデータをそのままBronze層のDeltaテーブルとして保存します。

bronze_reviews_df = spark.createDataFrame(reviews_pdf)
bronze_reviews_df.write.mode("overwrite").saveAsTable("bronze_kaizode_reviews")

KAIZODEのレビューデータには、レビュー本文・評価点数に加えて、あらかじめ日本語NLPで判定されたセンチメント(ポジティブ / ニュートラル / ネガティブ)や投稿者の年代・性別が含まれています。自前でセンチメント分析モデルを用意する必要がないため、この時点で分析可能な状態になっているのがポイントです。

主なカラム:

カラム内容
review_idレビューID
reviewレビュー本文
review_rating評価点数
sentimentセンチメント判定(ポジティブ / ニュートラル / ネガティブ)
published_at投稿日時
review_siteレビュー元サイト
reviewer_age / reviewer_gender投稿者属性

STEP 4:Bronze層 ― 売上・返品データの用意

本来ここには自社の基幹システムやECモールの管理画面からエクスポートした実データを配置します。本記事では検証用に合成データを生成します。

ただし完全なランダムデータでは相関分析のデモになりません。ここでは実際に取得したレビューの月次ネガティブ率をベースに、「ネガティブレビューが増えた月は返品率も上がる」という関係性を持たせた合成データを作ります。

import numpy as np

reviews_pdf["published_at"] = pd.to_datetime(reviews_pdf["published_at"])
reviews_pdf["year_month"] = reviews_pdf["published_at"].dt.to_period("M").astype(str)

monthly_negative_rate = (
    reviews_pdf.assign(is_negative=lambda d: d["sentiment"] == "ネガティブ")
    .groupby("year_month")["is_negative"]
    .mean()
    .rename("negative_rate")
    .reset_index()
    .sort_values("year_month")
)

np.random.seed(42)

BASE_ORDERS = 800          # 月間の基準注文件数
BASE_RETURN_RATE = 0.03    # ネガティブ率0%のときの基準返品率
NEGATIVE_IMPACT = 0.35     # ネガティブ率が返品率に与える係数

dummy_sales = monthly_negative_rate.copy()
dummy_sales["orders"] = (
    BASE_ORDERS
    + np.random.normal(0, 60, len(dummy_sales))
    - dummy_sales["negative_rate"] * 400
).round().astype(int).clip(lower=100)

dummy_sales["return_rate"] = (
    BASE_RETURN_RATE
    + dummy_sales["negative_rate"] * NEGATIVE_IMPACT
    + np.random.normal(0, 0.005, len(dummy_sales))
).clip(lower=0.005, upper=0.5)

dummy_sales["returns"] = (dummy_sales["orders"] * dummy_sales["return_rate"]).round().astype(int)
dummy_sales["revenue_jpy"] = dummy_sales["orders"] * np.random.randint(3200, 4200, len(dummy_sales))

bronze_sales_df = spark.createDataFrame(
    dummy_sales[["year_month", "orders", "returns", "return_rate", "revenue_jpy"]]
)
bronze_sales_df.write.mode("overwrite").saveAsTable("bronze_sales_returns")

NEGATIVE_IMPACT は「ネガティブレビュー比率が返品率にどれだけ効くか」を表す係数です。実データに差し替える際は当然不要になりますが、検証段階ではこの値を動かすことで「どの程度の相関があれば有意な発見と言えるのか」を体感できます。


STEP 5:Silver層 ― 月次センチメント指標への集計

生レビューをクレンジングし、月次の指標に集計します。

from pyspark.sql import functions as F

silver_reviews_df = (
    spark.table("bronze_kaizode_reviews")
    .withColumn("published_at_ts", F.to_timestamp("published_at"))
    .withColumn("year_month", F.date_format("published_at_ts", "yyyy-MM"))
    .select(
        "review_id", "review_target_name", "review_site",
        "review_rating", "sentiment", "review",
        "year_month", "published_at_ts",
    )
)
silver_reviews_df.write.mode("overwrite").saveAsTable("silver_kaizode_reviews")

silver_monthly_sentiment_df = (
    silver_reviews_df.groupBy("year_month")
    .agg(
        F.count("*").alias("review_count"),
        F.avg("review_rating").alias("avg_rating"),
        F.avg(F.when(F.col("sentiment") == "ネガティブ", 1).otherwise(0)).alias("negative_rate"),
        F.avg(F.when(F.col("sentiment") == "ポジティブ", 1).otherwise(0)).alias("positive_rate"),
    )
    .orderBy("year_month")
)
silver_monthly_sentiment_df.write.mode("overwrite").saveAsTable("silver_monthly_sentiment")
display(silver_monthly_sentiment_df)

センチメントを0/1に変換して平均を取ることで、月次のネガティブ率・ポジティブ率が求まります。


STEP 6:Gold層 ― 口コミと売上のJOIN

いよいよ本記事の核心です。月次センチメントと売上・返品データを year_month をキーにJOINします。

gold_df = (
    spark.table("silver_monthly_sentiment")
    .join(spark.table("bronze_sales_returns"), on="year_month", how="inner")
    .orderBy("year_month")
)
gold_df.write.mode("overwrite").saveAsTable("gold_sentiment_sales")
display(gold_df)

たった数行ですが、ここで**「レビュー分析ツールの中の世界」と「基幹システムの中の世界」が初めて接続されます**。これがレイクハウスに口コミデータを取り込む最大の意義です。


STEP 7:相関の可視化

gold_pdf = gold_df.toPandas()
correlation = gold_pdf["negative_rate"].corr(gold_pdf["return_rate"])
print(f"ネガティブ率と返品率の相関係数: {correlation:.2f}")

グラフを描画します。

import japanize_matplotlib   # 日本語フォント対応
import matplotlib.pyplot as plt

fig, ax1 = plt.subplots(figsize=(10, 5))

ax1.bar(gold_pdf["year_month"], gold_pdf["negative_rate"],
        color="#d64545", alpha=0.6, label="ネガティブ率")
ax1.set_ylabel("ネガティブ率")
ax1.set_xlabel("年月")
plt.xticks(rotation=45)

ax2 = ax1.twinx()
ax2.plot(gold_pdf["year_month"], gold_pdf["return_rate"],
         color="#2b5fa8", marker="o", label="返品率")
ax2.set_ylabel("返品率")

plt.title("トートバッグ:ネガティブレビュー率と返品率の推移")
plt.tight_layout()
plt.show()

つまずきポイント:グラフの日本語が文字化けする
Matplotlibのデフォルトフォントは日本語グリフを持たないため、そのままだと軸ラベルやタイトルが「豆腐(□)」になります。以下を先に実行してください。

%pip install japanize-matplotlib
dbutils.library.restartPython()

restartPython() を実行するとノートブック上の変数がリセットされるため、再起動後はSTEP 3以降を再実行してください。


STEP 8:AI/BI Genie ― 自然言語でデータに問いかける

ここからがDatabricksを使う本当の旨味です。作成したGold層テーブルをGenieに読み込ませると、SQLを書かずに自然言語で分析できるようになります。

Genie Spaceの作成

  1. 左サイドバーの Genie をクリック
  2. 右上の 「+ New」
  3. データソースとして workspace.kaizode_demo.gold_sentiment_sales を選択
  4. 「Create」 をクリック

回答精度を上げる設定

作成直後はカラム名だけからGenieが意味を推測するため、「指示(Instructions)」パネルにビジネス上の意味を書いておくと回答が安定します。

gold_sentiment_sales は月次の集計テーブルです。
- year_month: 年月(YYYY-MM)
- negative_rate: ネガティブレビュー比率
- return_rate: 商品の返品率
- orders: 月間注文件数
- revenue_jpy: 月間売上(円)
返品率が高い月はネガティブレビュー比率も高い傾向があります。

実際に質問してみる

チャット欄に日本語で質問を投げます。

返品率が最も高かった月とその要因は?

Genieは自動的にSQLを生成・実行し、以下のような回答を返してきました。


質問と同時に「推移の折れ線グラフ」「相関の散布図」まで自動生成され、生成されたSQLも確認できます。SQLを書けない事業部門の担当者が、自分でデータに問いかけられる状態になるわけです。

注意:AIの解釈は鵜呑みにしない

今回のGenieの回答には、続けて「2月は2年連続で返品率が高く、季節的な要因(冬物商品の品質問題など)も考えられます」という考察が付いていました。

しかし本記事の売上・返品データは合成データであり、季節性は一切組み込んでいません。Genieはデータから読み取れる以上の因果を、もっともらしく補完してしまったわけです。

これは自然言語分析ツール全般に共通する重要な注意点です。生成されたSQLと集計結果は信頼できますが、その先の「なぜそうなったか」という解釈は、必ず人間が事業知識と照らして検証する必要があります。Genieは仮説の生成装置であって、結論を出す装置ではありません。


STEP 9:ダッシュボードで定点観測する

Genieがアドホックな探索用だとすれば、日常的なモニタリングにはダッシュボードが向いています。

作成手順

  1. 左サイドバーの Dashboards → Create Dashboard
  2. 「データ」タブでデータソースを追加SELECT * FROM workspace.kaizode_demo.gold_sentiment_sales ORDER BY year_month
  3. 「キャンバス」タブでウィジェットを配置

構成例

配置ウィジェット内容
上段カウンター × 3平均返品率 / 平均ネガティブ率 / 累計注文数
中段左折れ線グラフネガティブ率と返品率の月次推移
中段右棒グラフ月次の注文件数と売上

ダッシュボードの各ウィジェットは自然言語での自動生成にも対応しており、「返品率の推移を折れ線グラフで」と指示するだけで作成できます。

完成したダッシュボードには 「Ask Genie」 ボタンが表示され、グラフを見ていて気になった点をその場で深掘りできます。「定点観測(ダッシュボード)」と「アドホックな深掘り(Genie)」がシームレスに繋がるのが、AI/BIの設計思想です。


本番運用に向けて

本記事では解説の都合上、すべてを1つのノートブックにまとめました。実運用では以下の点を見直すことになります。

レイヤーごとにジョブを分割する

Bronze / Silver / Gold をそれぞれ独立したノートブックまたはタスクにし、Databricks Workflowsで依存関係を持ったDAGとして構成します。レイヤーごとに実行頻度・リトライ・アラートを個別に設定できるため、「Bronzeの取り込みだけ失敗したので、そこだけリトライする」といった運用が可能になります。

宣言的パイプラインへの移行

さらに進んだ選択肢として、Lakeflow pipelines(旧Delta Live Tables)があります。各テーブルを「このクエリの結果」として宣言的に定義するだけで、依存関係の解決・差分処理・データ品質チェックをDatabricks側が自動管理します。パイプラインを量産していく段階では有力な選択肢です。

差分取り込みと冪等性

本記事では毎回全件を overwrite していますが、実運用ではKAIZODE APIの published_since パラメータを使った差分取得と、MERGE INTO によるUpsertに切り替えるべきです。レビュー件数が増えるほどAPI呼び出しコストと実行時間に効いてきます。

ロジックのモジュール化

fetch_kaizode_reviews() のような関数はノートブックに直書きせず、.py モジュールとして切り出してDatabricks Repos経由でインポートする形にすると、単体テストが書けるようになり保守性が上がります。


まとめ

本記事では、レビュー分析SaaSのAPIとDatabricksを繋ぎ、口コミデータと売上・返品データを統合分析するまでの流れを実際に動かしながら追いました。

要点を整理します。

  1. 口コミデータは、単体で見るより社内データと繋いだときに価値が跳ね上がる。「ネガティブが増えた」だけでは施策に繋がらないが、「返品率と連動している」と分かれば投資判断の材料になる
  2. メダリオンアーキテクチャで段階的に精製することで、集計ロジックを変更したくなってもBronze層から作り直せる再現性が担保される
  3. Genieによって、SQLを書けない事業部門もデータに直接問いかけられる。ただしAIの「解釈」は仮説であり、事業知識による検証が前提
  4. Free Editionだけで一連の検証が完結する。本番導入前の技術検証やPoCには十分な環境

レビュー分析ツールのUIにログインして眺めるフェーズから、自社のデータ基盤に口コミデータを取り込んで意思決定に組み込むフェーズへ。その第一歩として、この構成を試していただければと思います。

KAIZODEの製品デモ、資料ダウンロードはこちら

KAIZODEの外部連携についてはこちら

TDSEはDatabricksの認定パートナー(Databricks Silver Tier Partner)です。Databricksのお問い合わせはこちらからお願います。


参考リンク

一覧を見る

顧客の声を、
売れる理由に変えませんか。

KAIZODEの機能、AIレポート、無料デモで確認できることをご案内します。
資料ダウンロードや自社レビューでの活用相談もお気軽にお問い合わせください。

無料デモを予約するフォームからお問い合わせ 資料をダウンロードするフォームからお問い合わせ