# ランダム化比較実験（RCT）とは？Pythonでの実装方法も見ていこう！

> 本記事では、ビジネスシーンで因果関係を知りたい時に一番適切なアプローチがランダム化比較実験であり、非常に重要なので必ずおさえておきましょう！

- URL: https://toukei-lab.com/rct
- 公開: 2025.02.20 / 更新: 2025.09.30
- サイト: スタビジ（https://toukei-lab.com）

:::talk{who="umatan"}
本記事では、ビジネスシーンで因果関係を知りたい時に一番適切なアプローチがランダム化比較実験であり、非常に重要なので必ずおさえておきましょう！
:::

こんにちは！データサイエンティストのウマたん([@statistics1012](https://twitter.com/statistics1012?lang=ja))です。

ビジネスシーンで因果関係を確かめたいときってよくありますよね。

例えば、この施策って本当に効果あったのー？みたいな。

そんな時に、まず知っておきたいのがランダム化比較実験というアプローチ。

この記事で学んで、しっかり理解しておきましょう！

ちなみにランダム化比較実験を含めた統計的因果推論について詳しく知りたい方は以下の私のUdemy講座で学べますのでチェックしてみてください！

:::box
[【初心者向け】統計的因果推論を学びPythonで実装していこう！RCT・層別解析・マッチング法・傾向スコアを学ぼう！](https://www.udemy.com/course/causal-inference/?referralCode=F449A0AE8077B7269FD0)

[![Udemy](/wp-content/uploads/2022/11/109b1d5413b486743f6e463beeba02e2.jpg)](https://www.udemy.com/course/causal-inference/?referralCode=F449A0AE8077B7269FD0)

<table class="table">
<tbody>
<tr>
<th>【時間】</th>
<td><span>3.5時間</span></td>
</tr>
<tr>
<th>【レベル】</th>
<td><span>初級</span></td>
</tr>
</tbody>
</table>

統計的因果推論について詳しく知りたいならこのコース！

今なら購入時に「NZWCLGF4BTZENY6E」という講師クーポンコードを入れると90%オフ以上の割引価格になりますのでぜひご受講ください！

::button[このコースを見てみる]{href="https://www.udemy.com/course/causal-inference/?referralCode=F449A0AE8077B7269FD0" note="＼30日以内なら返金無料／"}
:::

以下のYouTube動画でも解説していますので合わせてチェックしてみてください！

::youtube{#GMiDmvg3fJ8}

## 相関関係と因果関係

さて、まずは相関関係と因果関係の違いについて見ていきましょう！

例えば、「**年収と一日の平均摂取カロリーには負の相関関係がある**」\
と聞いたらみなさんはどのように思いますか？

「よっしゃ！年収をあげるためにカロリーを抑えよう！」と思うでしょうか？

でも実際にはカロリーを低く抑えることによって年収が上がるということは期待されません。

なぜなら**相関関係があったとしても因果関係があるとは限らない**からです。

![](/wp-content/uploads/2018/08/75096042ebb8317433089ca9d0746044.png)

図1. 年収と摂取カロリーの散布図（仮想データ）

さて、先ほどの「年収と一日の摂取カロリー」には相関関係があることは間違いないです。

しかし、経験的に一日の摂取カロリーを低くしても年収が上がるという因果関係は認められないと思います。

それではなぜ「年収」を「摂取カロリー」の間に相関関係が見られたのでしょうか？\
それは、<mark>「年収」と「摂取カロリー」の裏に「年齢」という隠れた因子が存在する</mark>からです。

![](/wp-content/uploads/2018/08/39d68409c649550a0686a2a7e0612635.png)

図2. 交絡した因果グラフ

一般的に年齢が高くなると年収は上がります。そして年齢が高くなると摂取カロリーは低くなるでしょう。\
そのため摂取カロリーが低い人ほど年収が高くなったのです。

:::box
このような変数間の構造のことを**交絡**と呼びます。\
また、交絡しているときの相関を**擬似相関（偽相関）**&#x3068;呼びます。
:::

大事なのは<mark>相関関係があっても因果関係があるとは限らない</mark>ということです。

<https://toukei-lab.com/correlation-causal>

:::talk{who="umatan"}
相関と因果は別物だよ！
:::

## ランダム化比較実験とは？

![ランダム化比較試験](/wp-content/uploads/2022/11/37-1-e1740050862260-1024x479.jpg)

さて、相関と因果の違いを理解できたところで、早速ランダム化比較実験とは何なのか？見ていきましょう！

例えば、ある新薬を飲んでもらう群と通常のビタミン剤を飲んでもらう群に分けて新薬の効果を見る実験をするとします。

この時、ある集団を<mark>新薬を飲んでもらう群（**実験群・介入群・処置群**などと呼ぶ）とビタミン剤を飲んでもらう群（**対照群・統制群・コントロール群**などと呼ぶ）に分けて、結果の差を見ます。</mark>

集団の中のそれぞれの対象が介入群と対照群のどちらになるかを決定させることを割り付けと呼びます。

では、集団をどのように割り付ければ良いでしょうか。

例えば、男性なら新薬を飲んでもらい、女性ならビタミン剤を飲んでもらうという割り付けをしてみます。

すると、確かに結果の差を得ることは出来ますが、果たしてそれは新薬の効果によるものなのでしょうか。性別に由来する影響かもしれません。

この場合、<mark>性別のことを交絡因子</mark>と呼びます。

このように割り付けを適切に行わないと交絡を引き起こしてしまいます。

結局、如何にして交絡に対処するかが重要ということです。

因果効果を測定するには交絡因子を調整する必要があります。

ここで登場する最も適切な方法が、割り付けを完全にランダムに行う方法であり**ランダム化比較実験（Randomized Controlled Trial;RCT）**&#x3068;呼ばれるのです。

RCTでは例えば、一人一人にコインを投げてもらい表なら介入群、裏なら対照群とします。

これによって、いろんな潜在的な交絡因子があっても<mark>二つの群の分布は平均的に等しくなる</mark>ことが期待されます。

したがって、<mark>介入群と対照群の結果の差は介入によるものである</mark>と結論づけることが出来ます。

## ランダム化比較実験（RCT）をPythonで実装してみよう！

さて、それではこのRCTをPythonで実装してみましょう！

**今回は血圧を下げるサプリの効果があるのかないのか確かめるケース**を考えてみます。

まず、血圧を下げるサプリを試したい人を公募で募集し、彼らに血圧を下げるサプリを試して、それをサプリを摂取していない一般人と比較しました。

:::talk{who="umatan"}
この実験のどこに問題があるか分かるかな？
:::

そう、そもそも年齢が高く血圧が高い人ほど血圧を下げるサプリを飲みたいと思い応募してきている可能性が高く、比較対象には年齢という交絡因子が存在することが考えられます。

この誤った実験設定をそのままPythonコードに落とし込んでいきましょう！

```python
# --- データ生成 ---
N_obs = 1000

Age_obs = np.random.normal(50, 10, size=N_obs)

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 年齢が高いほどサプリを飲みやすい
p_supp_obs = sigmoid(0.3 * (Age_obs - 50))
Supplement_obs = np.random.binomial(1, p_supp_obs)

BloodPressure_obs = 130 + 0.3*Age_obs - 4.0*Supplement_obs + np.random.normal(0, 5, size=N_obs)

df_obs = pd.DataFrame({
    'Age': Age_obs,
    'Supplement': Supplement_obs,
    'BloodPressure': BloodPressure_obs
})

# --- まずは「年齢を無視」して単純比較 ---
mean_bp_supp_obs = df_obs[df_obs['Supplement'] == 1]['BloodPressure'].mean()
mean_bp_nosupp_obs = df_obs[df_obs['Supplement'] == 0]['BloodPressure'].mean()
diff_obs_naive = mean_bp_supp_obs - mean_bp_nosupp_obs

print(f"サプリ群 平均血圧:    {mean_bp_supp_obs:.2f}")
print(f"非サプリ群 平均血圧:  {mean_bp_nosupp_obs:.2f}")
print(f"単純比較(サプリ - 非サプリ): {diff_obs_naive:.2f}  ")
```

このコードの流れを見ていきましょう！

課題設定に沿って、1000人を対象に年齢が高いほどサプリを飲みやすいというような条件設定にします。

まず、Age_obs = np.random.normal(50, 10, size=N_obs)の部分で、年齢を平均50・標準偏差10の[正規分布](/gauss)に従う形でランダムに1000個生成しています。

続いて、sigmoidで[シグモイド関数](/sigmoid-function)を定義しています。シグモイド関数は[ロジスティック回帰](/%E3%83%AD%E3%82%B8%E3%82%B9%E3%83%86%E3%82%A3%E3%83%83%E3%82%AF%E5%9B%9E%E5%B8%B0)などに用いられる関数で、入力の値は0\~1の範囲に変換します。

すなわち数値を確率に変換する時に役立ちます。

入力が0の場合は出力は0.5になり、それより小さくなればなるほど0に近づき、大きければ大きいほど1に近づくのです。

今回は年齢を入力にしてサプリを飲む確率値を出力したいので、シグモイド関数を用いているのです。

さて、この関数の入力には0.3 \* (Age_obs – 50)を入れているので50歳の人はちょうど0.5の確率が出力されるようになっているわけですね。

ちなみに、たとえば被験者が60歳なら、Age_obs – 50 = 10 となり、計算は 0.3 \* 10 = 3 となります。シグモイド関数に3 を入れると約 0.95程度。つまり「ほぼ 95% の確率でサプリを飲む」となるわけです。

逆に40歳なら、Age_obs – 50 = -10 → 0.3 \* (-10) = -3となり、sigmoid(−3) は約 0.05。つまり「5% くらいの確率でしかサプリを飲まない」となるわけです。

続いて、Supplement_obs = np.random.binomial(1, p_supp_obs)の箇所では、二項分布に基づいて、確率値からサプリを飲むか飲まないかを0,1で出力しています。

続いて、以下の式では血圧の計測結果を出力しています。

```python
BloodPressure_obs = 130 + 0.3*Age_obs - 4.0*Supplement_obs + np.random.normal(0, 5, size=N_obs)
```

年齢が高ければ高いほど血圧が高くなり、サプリを飲んでいれば血圧が下がるような式になっています。

また個体差を出すために、乱数も発生させて加えています。

この結果をデータフレームに格納し、サプリを摂取した群としていない群の平均を比較してみると・・・結果は以下のようになりました。

:::box
サプリ群 平均血圧: 143.04\
非サプリ群 平均血圧: 143.06\
単純比較(サプリ – 非サプリ): -0.02
:::

本来であればサプリの効果があるはずなのに、ほぼ差がないことが分かります（※今回サプリを飲んでいるか否かで4.0を足しているので、本来であれば単純比較の差が4近くなるはず）。

それでは続いて、ランダム化比較実験（RCT）を用いて割り付けをおこなっていきましょう！

Pythonコードは以下になります。

```python
# --- データ生成 ---
N_rct = 1000

Age_rct = np.random.normal(50, 10, size=N_rct)

# サプリ割付：RCTなので年齢関係なく50%割付
Supplement_rct = np.random.binomial(1, 0.5, size=N_rct)

BloodPressure_rct = 130 + 0.3*Age_rct - 4.0*Supplement_rct + np.random.normal(0, 5, size=N_rct)

df_rct = pd.DataFrame({
    'Age': Age_rct,
    'Supplement': Supplement_rct,
    'BloodPressure': BloodPressure_rct
})

# --- 単純比較 ---
mean_bp_supp = df_rct[df_rct['Supplement'] == 1]['BloodPressure'].mean()
mean_bp_nosupp = df_rct[df_rct['Supplement'] == 0]['BloodPressure'].mean()
diff_rct = mean_bp_supp - mean_bp_nosupp

print(f"サプリ群 平均血圧:    {mean_bp_supp:.2f}")
print(f"非サプリ群 平均血圧:  {mean_bp_nosupp:.2f}")
print(f"単純比較(サプリ - 非サプリ): {diff_rct:.2f}  (ちゃんと効果が出る)")
```

今回は年齢に関係なくランダムに割り付けをおこなっています。血圧を求める式は同様。

結果は以下のようになりました。

:::box
サプリ群 平均血圧: 140.82\
非サプリ群 平均血圧: 145.12\
単純比較(サプリ – 非サプリ): -4.29 (ちゃんと効果が出る)
:::

ちゃんとサプリ群の方が4近く血圧が小さくなっており、効果が出ていることが分かりますね！

:::talk{who="robotan"}
それならどんな場合でもRCTをやればいいんじゃ、、、？
:::

ただ割り付けをランダムにすれば良いRCTは使い勝手が良さそうに見えますが、デメリットもあります。

そもそもそのような実験ができれば良いが、<mark>ランダムな割り付けが出来ない</mark>場合も多いのです

例えば、タバコと肺がんの関係を調べるために、ランダムに割り付けた人々に一日１０本のタバコを吸ってもらい肺がんになるまで実験するというのは倫理的に不可能です。

また、コストの問題もありますし、そもそもすでにデータが得られている場合にはどうしようもありません。

実験研究とは異なり割り付けがランダム化されていない方法は**観察研究**と呼ばれます。

現実問題では、観察データが多いこともあり、その場合は別のアプローチを試す必要があるのです。

## ランダム化比較実験　まとめ

ここまでで、まずおさえておきたいランダム化比較実験（RCT）についてまとめてきました。

もしランダムに割り付けができる状況であれば、ランダム化比較実験を実行して確実に因果を見定めていきましょう！

実際にはランダム化比較実験が難しいことも多く、そういった場合は様々な統計的因果推論のアプローチを試していくことになります。

統計的因果推論の分野の様々な手法について知りたい方は以下の記事をチェックしてみてください！

<https://toukei-lab.com/%E7%B5%B1%E8%A8%88%E7%9A%84%E5%9B%A0%E6%9E%9C%E6%8E%A8%E8%AB%96>

また冒頭でも紹介しましたが、統計的因果推論について詳しく知りたい方は以下の私のUdemy講座で学べますのでチェックしてみてください！

:::box
[【初心者向け】統計的因果推論を学びPythonで実装していこう！RCT・層別解析・マッチング法・傾向スコアを学ぼう！](https://www.udemy.com/course/causal-inference/?referralCode=F449A0AE8077B7269FD0)

[![Udemy](/wp-content/uploads/2022/11/109b1d5413b486743f6e463beeba02e2.jpg)](https://www.udemy.com/course/causal-inference/?referralCode=F449A0AE8077B7269FD0)

<table class="table">
<tbody>
<tr>
<th>【時間】</th>
<td><span>3.5時間</span></td>
</tr>
<tr>
<th>【レベル】</th>
<td><span>初級</span></td>
</tr>
</tbody>
</table>

統計的因果推論について詳しく知りたいならこのコース！

今なら購入時に「NZWCLGF4BTZENY6E」という講師クーポンコードを入れると90%オフ以上の割引価格になりますのでぜひご受講ください！

::button[このコースを見てみる]{href="https://www.udemy.com/course/causal-inference/?referralCode=F449A0AE8077B7269FD0" note="＼30日以内なら返金無料／"}
:::

さらに詳しくAIやデータサイエンスの勉強がしたい！という方は当サイト「スタビジ」が提供する[スタビジアカデミー](https://toukei-lab.com/achademy/)というサービスで体系的に学ぶことが可能ですので是非参考にしてみてください！

:::box
**AIデータサイエンス特化スクール「スタアカ」**

![スタアカ（スタビジアカデミー）のトップページ](/wp-content/uploads/2026/10/achademy-top.jpg)
:::

<table class="table">
<tbody>
<tr>
<th>【価格】</th>
<td>ライトプラン：1,280円/月（全コースが受講し放題）<br>
プレミアムプラン：129,800円（通常149,800円・買い切り）</td>
</tr>
<tr>
<th>【オススメ度】</th>
<td><span class="stars" role="img" aria-label="5点中5点" data-value="5"></span></td>
</tr>
<tr>
<th>【サポート体制】</th>
<td><span class="stars" role="img" aria-label="5点中4点" data-value="4"></span></td>
</tr>
<tr>
<th>【受講形式】</th>
<td>オンライン形式</td>
</tr>
<tr>
<th>【学習範囲】</th>
<td>統計学・機械学習・ディープラーニングを網羅的に学ぶ<br>
生成AI（LLM・RAG・プロンプトエンジニアリング）を学ぶ<br>
SQLとPythonを組み合わせて実データを使った様々なワークを行う<br>
実践的なビジネスフレームワークを学ぶ<br>
マーケティングの実行プラン策定</td>
</tr>
</tbody>
</table>

データサイエンティストとしての自分の経験をふまえてエッセンスを詰め込んだのがこちらのスタビジアカデミー、略して「[スタアカ](https://toukei-lab.com/achademy/)」！！

当メディアが運営するスクールです。

月額1,280円のライトプランで、統計学から機械学習・生成AIまで全コースが受講し放題です！

<mark>プレミアムプランでは、24時間以内の質問対応と現役データサイエンティストとの1on1（30分×4回）を実施します！</mark>

カリキュラム自体は、他のスクールと比較して圧倒的に良い自信があるのでぜひ受講してみてください！

他のスクールのカリキュラムはPythonでの機械学習実装だけに焦点が当たっているものが多く、実務に即した内容になっていないものが多いです。

<mark>そんな課題感に対して、実務で使うことの多いSQLや機械学習のビジネス導入プロセスの理解なども合わせて学べるボリューム満点のコース</mark>になっています！

Pythonが初めての人でも学べるようなカリキュラムにしておりますので是非チェックしてみてください！

ウォルマートのデータを使って商品の予測分析をしたり、実務で使うことの多いGoogleプロダクトのBigQueryを使って投球分析をしたり、データサイエンティストに必要なビジネス・マーケティングの基礎を学んでマーケティングプランを作ってもらったりする盛りだくさんの内容になってます！

:::box
**・BigQuery上でSQL、Google Colab上でPythonを使い野球の投球分析**\
**・世界最大手小売企業のウォルマートの実データを用いた需要予測**\
**・ビジネス・マーケティングの基礎を学んで実際の企業を題材にしたマーケティングプランの策定**\
**・生成AIのAPIを使ってチャットボットやAIエージェントを作る**
:::

::button[スタアカの受講はこちら]{href="https://toukei-lab.com/achademy/" note="＼今すぐ試す／"}