---
title: RWD 分析を R で
tags:  #r with pharma lab meetup 1  
author: [森岡裕[SASユーザー総会世話人]](https://www.docswell.com/user/6484025)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/DJY42W447M.jpg?width=480
description: RWD 分析を R で by 森岡裕[SASユーザー総会世話人]
published: April 06, 26
canonical: https://www.docswell.com/s/6484025/5R82G9-2026-04-06-113246
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/DJY42W447M.jpg)

1
RWD
分析を で
西川 寛来
2026-04-08
R with Pharma Lab#1
R


# Page. 2

![Page Image](https://bcdn.docswell.com/page/V7NY89Y6E8.jpg)

スライドはこちら
2
https://nissinbo.github.io/RwPL_1_rwd/
R with Pharma Lab#1


# Page. 3

![Page Image](https://bcdn.docswell.com/page/YJ9PK2PR73.jpg)

自己紹介
3
西川寛来
→ 製薬業界で修行中
→ LinkedIn
→ GitHub
R with Pharma Lab#1


# Page. 4

![Page Image](https://bcdn.docswell.com/page/GJ8DR5DGJD.jpg)

こんな話をします 🙆
4
分析におけるデータハンドリングの tips
データベース研究で便利なパッケージ
OMOP CDM の紹介
RWD
R with Pharma Lab#1


# Page. 5

![Page Image](https://bcdn.docswell.com/page/LJLMKYMXER.jpg)

RWD
分析の大変なところ 🤔
製薬企業でよく利用される RWD
医療情報データベース
→ レセプトデータ
→ 電子カルテデータ
解析上の難しい点・勘所
大規模データのハンドリング
治療の連続性 (処方継続、中止、切り替え) の追跡
ICD-10 等のコード体系
R with Pharma Lab#1
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/47MY2NY37W.jpg)

結論 これで学ぼう
6
:
疫学のための R ハンドブック
→ 疫学データ解析の実践ガイド
→ 可視化・統計・レポーティングなど幅広くカバー
これが最速だと思います。が、本発表ではもっとマニアックな tips をお伝えします
R with Pharma Lab#1


# Page. 7

![Page Image](https://bcdn.docswell.com/page/P7R9MD9RE9.jpg)

7
基本的な操作
R with Pharma Lab#1


# Page. 8

![Page Image](https://bcdn.docswell.com/page/PJXQV1QY7X.jpg)

非等価結合
8
🔗
RWD 研究で頻出のシチュエーションで便利
→ 処方日より前の直近の検査値を取得したい
→ 診断日から n 日以内の入院を探したい
1
2
3
4
5
6
7
8
9
10
11
12
13
(Non-equi joins)
# 処方テーブル
rx &lt;- tibble(patient_id = c(1, 1, 2), rx_date = as.Date(c(&quot;2023-01-15&quot;, &quot;2023-06-01&quot;, &quot;2023-03-10&quot;)))
# 検査値テーブル
lab &lt;- tibble(
patient_id = c(1, 1, 1, 2),
lab_date
= as.Date(c(&quot;2022-12-01&quot;, &quot;2023-01-10&quot;, &quot;2023-05-20&quot;, &quot;2023-02-15&quot;)),
hba1c
= c(7.2, 7.5, 6.8, 8.1)
)
# 処方日以前の直近の検査値を非等価結合で取得
result &lt;- rx |&gt;
left_join(lab, join_by(patient_id, closest(rx_date &gt;= lab_date)))
left_join()
1
行で完結！
1
→ filter() → arrange() → slice_head() と同様の処理が、join_by()
R with Pharma Lab#1


# Page. 9

![Page Image](https://bcdn.docswell.com/page/3JK9Q294JD.jpg)

治療継続性
e.g.,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(Persistency)
の定義 💉
9
「治療が 15 日以上途切れたら中断とみなす」みたいなルールを定義したい
rx &lt;- tribble(
~patient_id, ~start_date,
~end_date,
1,
&quot;2024-01-01&quot;, &quot;2024-04-01&quot;,
1,
&quot;2024-01-15&quot;, &quot;2024-02-01&quot;,
1,
&quot;2024-02-15&quot;, &quot;2024-03-01&quot;
) |&gt;
mutate(start_date = as.Date(start_date), end_date = as.Date(end_date))
# 各処方を lubridate の interval 形式に変換
rx_intervals &lt;- rx |&gt;
arrange(patient_id, start_date) |&gt;
group_by(patient_id) |&gt;
mutate(
rx_interval
= interval(start_date, end_date),
running_max_end = accumulate(end_date, max),
prev_coverage
= lag(interval(first(start_date),
running_max_end))
)
R with Pharma Lab#1
1
2


# Page. 10

![Page Image](https://bcdn.docswell.com/page/LE3WP4WDE5.jpg)

単純な
lead/lag
の比較だと
❌ lead/lag の比較
処方1
処方2
処方3
|===========1/1〜4/1===========|
|=1/15〜2/1=|
|=2/15〜3/1=|
↑ 処方2と処方3の間の gap で
誤って「中断」と判定
10
…?
✅ “最遅終了日”を更新するやり方
処方1
処方2
処方3
|===========1/1〜4/1===========|
↓ running_max_end = 4/1
|=1/15〜2/1=| → 4/1以前: 継続✅
|=2/15〜3/1=| → 4/1以前: 継続✅
治療の連続性の判定には、lead()/lag() だとダメなことがある！
accumulate(end_date, max) とすると確実
R with Pharma Lab#1


# Page. 11

![Page Image](https://bcdn.docswell.com/page/8EDKLQK27G.jpg)

11
大規模データへの対応
R with Pharma Lab#1


# Page. 12

![Page Image](https://bcdn.docswell.com/page/V7PK2LKLJ8.jpg)

あなたのデータ環境は？
が用意されている → SQL で抽出すれば OK
→ SQL または dbplyr
DB がない / R 上で大きなデータを扱う → DuckDB
→ duckplyr
DB
R with Pharma Lab#1
12


# Page. 13

![Page Image](https://bcdn.docswell.com/page/2JVVDQV6JQ.jpg)

DB
1
2
3
4
5
があるなら
: SQL,
library(DBI)
library(dplyr)
library(dbplyr)
con &lt;- dbConnect(RPostgres::Postgres(), ...)
SQL
1
2
3
4
5
6
7
8
9
dbplyr
sql &lt;- &quot;
SELECT patient_id, drug, COUNT(*) AS n_rx
FROM rx
WHERE start_date &gt;= DATE &#039;2023-01-01&#039;
AND start_date &lt; DATE &#039;2024-01-01&#039;
GROUP BY patient_id, drug
&quot;
n_rx &lt;- dbGetQuery(con, sql)
どちらも
OK
# DB接続
dbplyr
1 n_rx &lt;- con |&gt;
2
tbl(&quot;rx&quot;) |&gt;
3
filter(
4
between(
5
start_date,
6
as.Date(&quot;2023-01-01&quot;),
7
as.Date(&quot;2024-01-01&quot;)
8
)
9
) |&gt;
10
count(patient_id, drug) |&gt;
11
collect() # ここで初めて R に持ってくる
R with Pharma Lab#1
13


# Page. 14

![Page Image](https://bcdn.docswell.com/page/5EGLYWL2JL.jpg)

それでも「 上で大きなデータ」を扱いたい場面がある
R
ウチには DB なんてないよ！ CSV ファイルでしかデータもらえないよ！
DB はあるけど、権限の都合で DB 上に一時テーブルが作れない
そんな時には duckplyr
R with Pharma Lab#1
14


# Page. 15

![Page Image](https://bcdn.docswell.com/page/4JQYM3Y97P.jpg)

duckplyr
のうれしさ
15
を準備しなくても、R 上で大規模データを扱える
速い
dplyr 記法で書ける
DB
1 library(duckplyr)
2
3 penguins_duck &lt;- penguins |&gt;
4
as_duckdb_tibble() |&gt; # duckplyr data frame に変換
5
group_by(species) |&gt; # 普通に dplyr を書くだけ
6
summarise(mean_bill_length = mean(bill_len, na.rm = TRUE))
R with Pharma Lab#1


# Page. 16

![Page Image](https://bcdn.docswell.com/page/K74WV1ZRE1.jpg)

dplyr
Code
と duckplyr の速度比較
速いです
R with Pharma Lab#1
16


# Page. 17

![Page Image](https://bcdn.docswell.com/page/LJ1Y3GRVEG.jpg)

17
フローチャート作成
R with Pharma Lab#1


# Page. 18

![Page Image](https://bcdn.docswell.com/page/GJWGPK1372.jpg)

CONSORT diagram
とは
臨床研究において患者選択や割り当ての流れを示したフローチャート
集団選択が複雑な RWD 研究ではとても重要！
R with Pharma Lab#1
18


# Page. 19

![Page Image](https://bcdn.docswell.com/page/4EZLKZPG73.jpg)

よくある
🤔
CONSORT diagram
の作り方
コピペ、体裁を整える作業で消耗するほど人生は長くない
データと紐付けて、患者数を自動で入れたい。どうせ明日には除外基準が 1 つ追加されて、患者数も変わるんだし…
図はすべて ggplot2 で書きたい
R with Pharma Lab#1
19


# Page. 20

![Page Image](https://bcdn.docswell.com/page/Y76WQZMQ7V.jpg)

CONSORT diagram
を作るための パッケージ
R
flowchart
→ “Tidy Flowchart Generator”
→ dplyr っぽく piping してフローチャートを作成
R with Pharma Lab#1
20


# Page. 21

![Page Image](https://bcdn.docswell.com/page/G75MRWZ274.jpg)

flowchart
の使い方
21
1 safo |&gt;
2
as_fc(label = &quot;Patients assessed for eligibility&quot;) |&gt;
3
fc_filter(!is.na(group), label = &quot;Randomized&quot;, show_exc = TRUE) |&gt;
4
fc_split(group) |&gt;
5
fc_filter(itt == &quot;Yes&quot;, label = &quot;Included in ITT&quot;) |&gt;
6
fc_draw()
患者集団やコードセットに変更があっても、患者数のコピペは不要！
R with Pharma Lab#1
1
2
3
4


# Page. 22

![Page Image](https://bcdn.docswell.com/page/9J29DQR1ER.jpg)

22
まとめ
R with Pharma Lab#1


# Page. 23

![Page Image](https://bcdn.docswell.com/page/DEY42WD4JM.jpg)

RWD
分析を でやっていきましょう
R
📦 基本的な操作
を使った非等価結合は便利
治療継続性は lubridate の interval と accumulate() を組み合わせると確実
join_by()
🚀 大規模データ
があるなら SQL / dbplyr
ローカル の R でも duckplyr を使うだけで高速化！
DB
🗂
フローチャート作成
全部 R でやって、コピペ作業から解放
R with Pharma Lab#1
23


# Page. 24

![Page Image](https://bcdn.docswell.com/page/VJNY896678.jpg)

24
Enjoy
🙋
R with Pharma Lab#1


