代码
library(ivdtools)
library(readr)定性(qualitative)分析评价候选方法与参考方法在阳性/阴性判定上的一致程度,对应 CLSI EP12。 ivdtools 提供 raw_to_table() 从原始配对数据构建四格表,counts_to_table() 从已有的 TP/FP/TN/FN 计数直接构建,并配套 diagnostics()(灵敏度、特异度、PPV、NPV、似然比等)、kappa()(Kappa 与 PABAK)与 mcnemar()(配对差异检验)三个分析方法。定量结果需转定性时可用 continuous_to_binary()。
本文用三个示例演示三种数据来源的完整分析。示例数据为确定性的教学数据,阳性方向与阈值应依据 方案确定。
library(ivdtools)
library(readr)| 函数 | 主要用途 | 关键输入或输出 |
|---|---|---|
raw_to_table() |
原始配对数据构建四格表 | candidate、reference、positive、na.rm |
counts_to_table() |
由 TP/FP/TN/FN 构建四格表 | candidate/reference 命名 |
continuous_to_binary() |
定量转定性 | cutoff(≥ cutoff 为 1) |
describe() |
原始数据描述 | 仅 raw_to_table() 来源可用 |
diagnostics() |
诊断准确性指标 | ci.method、prevalence |
kappa() |
Kappa / PABAK | prevalence 切换 |
mcnemar() |
配对差异检验 | 不一致对 <25 用精确检验 |
qual <- read_csv("./data/qualitative-raw.csv", show_col_types = FALSE)
qual <- as.data.frame(qual)
str(qual)'data.frame': 60 obs. of 5 variables:
$ id : chr "S001" "S002" "S003" "S004" ...
$ new : chr "positive" "negative" "negative" "negative" ...
$ gold : chr "positive" "negative" "negative" "negative" ...
$ age : num 46.1 44.7 65.7 60 64.6 32.7 47 40.9 38.4 48.1 ...
$ gender: chr "M" "F" "M" "F" ...
table(qual$gold)
negative positive
36 24
table(qual$new)
negative positive
36 24
qa <- raw_to_table(
qual,
candidate = "new",
reference = "gold",
id = "id",
positive = "positive"
)
qa
Fourfold Table
Source : raw data
Total n : 60
Duplicate IDs : none
Candidate : new
Reference : gold
2x2 Contingency Table
----------------------------------------
gold
positive negative Sum
----------------------------------------
new positive 23 1 24
negative 1 35 36
sum 24 36 60
----------------------------------------
参数说明:
raw_to_table()要求候选与参考列都恰好有 2 个水平;positive指定阳性水平 (用于因子/字符列的水平映射);na.rm控制是否删除缺失行。id可选,用于重复样本检测。
qa <- describe(qa)
Data Summary
Rows: 60
Columns: 5
ID: 60 unique, no duplicates
new
negative 36 ( 60.0%)
positive 24 ( 40.0%)
gold
negative 36 ( 60.0%)
positive 24 ( 40.0%)
age
Mean (SD): 51.05 (13.45)
Median (Q1-Q3): 48.90 (42.15 - 57.28)
Range: 24.30 - 90.10
gender
F 32 ( 53.3%)
M 28 ( 46.7%)
describe() 仅对 raw_to_table() 来源可用,输出行数、ID 重复、各列摘要与缺失情况。
qa <- diagnostics(qa, ci.method = "wilson")
Diagnostic Performance Summary
Sensitivity 0.958 (0.798, 0.993)
Specificity 0.972 (0.858, 0.995)
PPV 0.958 (0.798, 0.993)
NPV 0.972 (0.858, 0.995)
Accuracy 0.967 (0.886, 0.991)
Prevalence 0.400 (0.286, 0.526)
LR+ 34.500 (4.986, 238.724)
LR- 0.043 (0.006, 0.292)
Odds Ratio 805.000 (47.921, 13522.837)
# PPV & NPV are based on data prevalence of 0.400.
# Confidence intervals for proportions use 'wilson' method.
qa$diagnostics[c("sensitivity", "specificity", "ppv", "npv", "accuracy")]$sensitivity
est lower upper
0.9583333 0.7975819 0.9926065
$specificity
est lower upper
0.9722222 0.8583028 0.9950796
$ppv
est lower upper
0.9583333 0.7975819 0.9926065
$npv
est lower upper
0.9722222 0.8583028 0.9950796
$accuracy
est lower upper
0.9666667 0.8863623 0.9908107
本例灵敏度 0.958、特异度 0.972。若已知目标人群患病率,可用 prevalence 重算 PPV/NPV:
qa <- diagnostics(qa, prevalence = 0.4)
Diagnostic Performance Summary
Sensitivity 0.958 (0.798, 0.993)
Specificity 0.972 (0.858, 0.995)
PPV 0.958 (0.790, 0.993)
NPV 0.972 (0.864, 0.995)
Accuracy 0.967 (0.886, 0.991)
Prevalence 0.400
LR+ 34.500 (4.986, 238.724)
LR- 0.043 (0.006, 0.292)
Odds Ratio 805.000 (47.921, 13522.837)
# PPV & NPV are based on user-specified prevalence of 0.400.
# Confidence intervals for proportions use 'wilson' method.
qa$diagnostics[c("ppv", "npv")]$ppv
est lower upper
0.9583333 0.7895852 0.9926193
$npv
est lower upper
0.9722222 0.8641373 0.9950711
参数说明:
diagnostics()的ci.method可选 7 种比例置信区间方法(默认"wilson"); 给出prevalence时 PPV/NPV 按贝叶斯公式重算,否则基于数据患病率。
qa <- kappa(qa)
Cohen's Kappa
new vs gold
n = 60
Kappa 0.9306
SE 0.0483
95% CI (0.8359, 1.0000)
Observed agreement 0.9667
Expected agreement 0.5200
qa <- kappa(qa, prevalence = 0.5)
PABAK
new vs gold
n = 60
Kappa 0.9333
SE 0.0463
95% CI (0.8425, 1.0000)
Observed agreement 0.9667
Expected agreement 0.5000
# PABAK (prevalence = 0.500): 2 * p_obs - 1, assumes expected agreement = 0.5
参数说明:
kappa()给出 Cohen’s Kappa;当给出prevalence时改为计算 PABAK (2·p_obs − 1)。两者对患病率偏倚的处理不同,报告时应注明方法。
qa <- mcnemar(qa)
McNemar Test
new vs gold
Discordant pairs: b (pos, neg) = 1, c (neg, pos) = 1
n (b + c) = 2
Method: Exact binomial test
P-value: 1.0000
Conclusion: Not significant at 95% confidence level
不一致对 b+c = 2 < 25,函数自动使用精确二项检验。
summary(qa)
Qualitative Analysis - summary
-------------------------------------------------
Fourfold Table
Source : raw data
Total n : 60
Duplicate IDs : none
Candidate : new
Reference : gold
2x2 Contingency Table
----------------------------------------
gold
positive negative Sum
----------------------------------------
new positive 23 1 24
negative 1 35 36
sum 24 36 60
----------------------------------------
Analyses performed:
[x] Describe
[x] Diagnostics
[x] Kappa
[x] McNemar
Data Summary
Rows: 60
Columns: 5
ID: 60 unique, no duplicates
new
negative 36 ( 60.0%)
positive 24 ( 40.0%)
gold
negative 36 ( 60.0%)
positive 24 ( 40.0%)
age
Mean (SD): 51.05 (13.45)
Median (Q1-Q3): 48.90 (42.15 - 57.28)
Range: 24.30 - 90.10
gender
F 32 ( 53.3%)
M 28 ( 46.7%)
Diagnostic Performance Summary
Sensitivity 0.958 (0.798, 0.993)
Specificity 0.972 (0.858, 0.995)
PPV 0.958 (0.790, 0.993)
NPV 0.972 (0.864, 0.995)
Accuracy 0.967 (0.886, 0.991)
Prevalence 0.400
LR+ 34.500 (4.986, 238.724)
LR- 0.043 (0.006, 0.292)
Odds Ratio 805.000 (47.921, 13522.837)
# PPV & NPV are based on user-specified prevalence of 0.400.
# Confidence intervals for proportions use 'wilson' method.
PABAK
new vs gold
n = 60
Kappa 0.9333
SE 0.0463
95% CI (0.8425, 1.0000)
Observed agreement 0.9667
Expected agreement 0.5000
# PABAK (prevalence = 0.500): 2 * p_obs - 1, assumes expected agreement = 0.5
McNemar Test
new vs gold
Discordant pairs: b (pos, neg) = 1, c (neg, pos) = 1
n (b + c) = 2
Method: Exact binomial test
P-value: 1.0000
Conclusion: Not significant at 95% confidence level
已有计数时无需原始数据:
tab <- counts_to_table(
tp = 80, fp = 5, tn = 120, fn = 3,
candidate = "new method",
reference = "gold standard"
)
tab
Fourfold Table
Source : counts
Total n : 208
Candidate : new method
Reference : gold standard
2x2 Contingency Table
-----------------------------------------------
gold standard
positive negative Sum
-----------------------------------------------
new method positive 80 5 85
negative 3 120 123
sum 83 125 208
-----------------------------------------------
tab <- diagnostics(tab)
Diagnostic Performance Summary
Sensitivity 0.964 (0.899, 0.988)
Specificity 0.960 (0.910, 0.983)
PPV 0.941 (0.870, 0.975)
NPV 0.976 (0.931, 0.992)
Accuracy 0.962 (0.926, 0.980)
Prevalence 0.399 (0.335, 0.467)
LR+ 24.096 (10.198, 56.934)
LR- 0.038 (0.012, 0.114)
Odds Ratio 640.000 (148.773, 2753.180)
# PPV & NPV are based on data prevalence of 0.399.
# Confidence intervals for proportions use 'wilson' method.
tab <- kappa(tab)
Cohen's Kappa
new method vs gold standard
n = 208
Kappa 0.9201
SE 0.0277
95% CI (0.8659, 0.9744)
Observed agreement 0.9615
Expected agreement 0.5184
tab <- mcnemar(tab)
McNemar Test
new method vs gold standard
Discordant pairs: b (pos, neg) = 5, c (neg, pos) = 3
n (b + c) = 8
Method: Exact binomial test
P-value: 0.7266
Conclusion: Not significant at 95% confidence level
summary(tab)
Qualitative Analysis - summary
-------------------------------------------------
Fourfold Table
Source : counts
Total n : 208
Candidate : new method
Reference : gold standard
2x2 Contingency Table
-----------------------------------------------
gold standard
positive negative Sum
-----------------------------------------------
new method positive 80 5 85
negative 3 120 123
sum 83 125 208
-----------------------------------------------
Analyses performed:
[ ] Describe
[x] Diagnostics
[x] Kappa
[x] McNemar
Diagnostic Performance Summary
Sensitivity 0.964 (0.899, 0.988)
Specificity 0.960 (0.910, 0.983)
PPV 0.941 (0.870, 0.975)
NPV 0.976 (0.931, 0.992)
Accuracy 0.962 (0.926, 0.980)
Prevalence 0.399 (0.335, 0.467)
LR+ 24.096 (10.198, 56.934)
LR- 0.038 (0.012, 0.114)
Odds Ratio 640.000 (148.773, 2753.180)
# PPV & NPV are based on data prevalence of 0.399.
# Confidence intervals for proportions use 'wilson' method.
Cohen's Kappa
new method vs gold standard
n = 208
Kappa 0.9201
SE 0.0277
95% CI (0.8659, 0.9744)
Observed agreement 0.9615
Expected agreement 0.5184
McNemar Test
new method vs gold standard
Discordant pairs: b (pos, neg) = 5, c (neg, pos) = 3
n (b + c) = 8
Method: Exact binomial test
P-value: 0.7266
Conclusion: Not significant at 95% confidence level
describe(tab) # counts 来源无原始数据,describe() 不可用counts_to_table() 构建的对象没有原始数据,因此 describe() 不可用;diagnostics()、kappa()、 mcnemar() 均正常。
候选方法为定量结果 result,参考为定性 gold:
cont <- read_csv("./data/qualitative-continuous.csv", show_col_types = FALSE)
cont <- as.data.frame(cont)
str(cont)'data.frame': 50 obs. of 3 variables:
$ id : chr "S001" "S002" "S003" "S004" ...
$ result: num 10.11 13.06 1.53 7.78 4.98 ...
$ gold : chr "positive" "positive" "negative" "negative" ...
按 cutoff = 8 转二分类:
cont_bin <- continuous_to_binary(cont, cols = "result", cutoff = 8)
head(cont_bin)continuous_to_binary() 生成 result_binary 列(≥ cutoff 为 1,否则 0)。为满足 raw_to_table() 的 positive 映射要求,先重标为与参考一致的标签:
cont_bin$result_binary_lab <- ifelse(cont_bin$result_binary == 1, "positive", "negative")qa3 <- raw_to_table(
cont_bin,
candidate = "result_binary_lab",
reference = "gold",
id = "id",
positive = "positive"
)
qa3 <- diagnostics(qa3)
Diagnostic Performance Summary
Sensitivity 0.952 (0.773, 0.992)
Specificity 0.897 (0.736, 0.964)
PPV 0.870 (0.679, 0.955)
NPV 0.963 (0.817, 0.993)
Accuracy 0.920 (0.812, 0.968)
Prevalence 0.420 (0.294, 0.558)
LR+ 9.206 (3.140, 26.994)
LR- 0.053 (0.008, 0.361)
Odds Ratio 173.333 (16.746, 1794.100)
# PPV & NPV are based on data prevalence of 0.420.
# Confidence intervals for proportions use 'wilson' method.
qa3$diagnostics[c("sensitivity", "specificity", "accuracy")]$sensitivity
est lower upper
0.9523810 0.7733064 0.9915440
$specificity
est lower upper
0.8965517 0.7361492 0.9641851
$accuracy
est lower upper
0.9200000 0.8116175 0.9684505
注意:
positive指定的水平必须同时存在于两列中,因此先把二值列重标为positive/negative。 若不指定positive,函数可能按排序水平把阳性/阴性方向颠倒,导致 TP/FP 翻转,务必核对。