同じ量の薬を投与しても、同じ濃度になるとは限りません。ペムブロリズマブの公開PopPKモデルを使って、体重だけを変えたときの平均濃度を計算します。
ここでは、固定用量を検討した研究[1]に登場する静脈内200 mg・3週ごとの投与を計算条件にします。新たに患者データへモデルを当てはめる記事ではなく、公表モデルの一部分を使う小さな数値例です。
図で見る
横軸は体重、縦軸は定常状態での21日間の平均濃度です。投与直後や次回投与直前の濃度ではありません。
| 体重 | 消失の速さを表すCL(L/day) | 平均濃度(mg/L) | 76.8 kgに対する比 |
|---|---|---|---|
| 40 kg | 0.149 | 63.8 | 1.47 |
| 76.8 kg | 0.220 | 43.3 | 1.00 |
| 120 kg | 0.287 | 33.2 | 0.77 |
mg/Lはµg/mLと同じ数値になります。このモデル条件では、体重が重いほど薬を除去する能力であるクリアランス(CL)が大きくなり、同じ200 mgに対する平均濃度が低くなります。
計算は二つの式だけ
AhamadiらのTable 3の推定値[2]から、体重の項だけを取り出します。
$$
CL(W)=0.22\left(\frac{W}{76.8}\right)^{0.595}\quad\mathrm{L/day}
$$
他の条件は、男性、アルブミン39.6 g/L、eGFR 88.47、腫瘍径の和89.6 mm、非NSCLC、ECOG-PS 0、イピリムマブ前治療なしに固定します。個人間のランダムなばらつきも加えません。
CLが時間によらず一定で、線形の静脈内PKを仮定すると、定常状態では1投与間隔の間に入る量と消える量が一致します。そのため、平均濃度は
$$
C_{\mathrm{avg,ss}}=\frac{\mathrm{Dose}}{CL\times\mathrm{Interval}}
=\frac{200}{CL\times21}\quad\mathrm{mg/L}
$$
で求まります。元のモデルは2コンパートメントですが、平均濃度だけなら分布容積や点滴時間はこの式に入りません。 山と谷を知りたい場合には、濃度の時間曲線を計算する必要があります。
出典の値が二通りある点に注意
Table 3の本表ではCLが0.22、体重の指数が0.595ですが、脚注の式では0.202と0.578です[2]。今回は本表の値を使いました。
脚注の値でも再計算すると、40・76.8・120 kgの平均濃度はそれぞれ68.7・47.1・36.4 mg/Lでした。絶対値は変わりますが、体重が重い条件で平均濃度が低くなる方向は同じです。これは出典の記載差への確認であり、患者の予測区間や信頼区間ではありません。
Pythonで再計算
Python 3.12、NumPy 1.26.4、Matplotlib 3.9.1で実行しました。以下をcalculate.pyとして保存してpython calculate.pyを実行すると、図と数値を作れます。
コードを表示
"""Weight-only average-exposure calculation using Ahamadi 2017 Table 3."""
from pathlib import Path
import json
import numpy as np
import matplotlib.pyplot as plt
ROOT = Path(__file__).resolve().parent
DOSE, INTERVAL, REF_WEIGHT = 200.0, 21.0, 76.8
def exposure(weight, cl_ref=0.22, exponent=0.595):
weight = np.asarray(weight, dtype=float)
if np.any(weight <= 0):
raise ValueError('Weight must be positive')
clearance = cl_ref * (weight / REF_WEIGHT) ** exponent
return clearance, DOSE / (clearance * INTERVAL)
def main():
(ROOT / 'figures').mkdir(exist_ok=True)
(ROOT / 'results').mkdir(exist_ok=True)
selected = np.array([40.0, 76.8, 120.0])
cl, avg = exposure(selected)
_, alternative = exposure(selected, 0.202, 0.578)
rows = [dict(weight_kg=float(w), clearance_L_day=float(c),
average_mg_L=float(a), relative_to_reference=float(a / exposure(REF_WEIGHT)[1]),
footnote_average_mg_L=float(f))
for w, c, a, f in zip(selected, cl, avg, alternative)]
(ROOT / 'results' / 'summary.json').write_text(
json.dumps(rows, indent=2), encoding='utf-8')
weights = np.linspace(40, 120, 201)
fig, ax = plt.subplots(figsize=(7, 4.5), layout='constrained')
ax.plot(weights, exposure(weights)[1], color='#0072B2', lw=2)
ax.scatter(selected, avg, color='#0072B2', s=35, zorder=3)
for w, a in zip(selected, avg):
ax.annotate(f'{w:g} kg: {a:.1f}', (w, a), xytext=(0, 9),
textcoords='offset points', ha='center', fontsize=10)
ax.set(xlim=(32, 128), ylim=(0, 80), xlabel='Body weight (kg)',
ylabel='Steady-state average concentration (mg/L)')
ax.set_title('Pembrolizumab: same fixed dose, different weight',
loc='left', fontsize=12, pad=30)
ax.text(0, 1.02, '200 mg IV every 21 days; other covariates fixed; no random effects',
transform=ax.transAxes, fontsize=9)
ax.spines[['top', 'right']].set_visible(False)
ax.grid(axis='y', color='#dddddd', lw=0.6)
fig.savefig(ROOT / 'figures' / 'pembrolizumab-weight.png', dpi=180)
print(json.dumps(rows, indent=2))
if __name__ == '__main__':
main()
検算では、別途2コンパートメントの30分点滴を定常状態で計算し、21日間の濃度曲線を数値積分した平均値が、この式と一致することを確認しました。
この計算から何が分かるか
固定用量は、平均濃度を全員で同じにする方式ではありません。 体重とCLの関係をモデルへ入れると、同じ投与量でも濃度の違いが生まれます。
ただし、この図は体重以外を揃えたモデル上の比較であり、実際の患者集団の平均や分布を示していません。2017年の時間不変CLモデルを使った例で、治療中のCL変化も扱っていません。
濃度の差だけから、効果・安全性の差や体重に応じた用量変更の必要性は判断できません。今回は、公開モデルの共変量を数値へ変換する学習用の計算です。
参考文献
- Freshwater T, et al. Evaluation of dosing strategy for pembrolizumab for oncology indications. Journal for ImmunoTherapy of Cancer. 2017;5:43. doi:10.1186/s40425-017-0242-5
- Ahamadi M, et al. Model-Based Characterization of the Pharmacokinetics of Pembrolizumab: A Humanized Anti–PD-1 Monoclonal Antibody in Advanced Solid Tumors. CPT: Pharmacometrics & Systems Pharmacology. 2017;6:49–57. doi:10.1002/psp4.12139
