首页 > 解决方案 > 在 r 中使用多个条件将控件与案例匹配

问题描述

我想在两个条件下controls为每个匹配 2 case

age差值应在±2之间;

income差值应在±2之间。

如果一个案例超过2controls个,我只需要controls随机选择2个。有一个例子:

例子

数据

dat = structure(list(id = c(1, 2, 3, 4, 111, 222, 333, 444, 555, 666, 
                     777, 888, 999, 1000), 
              age = c(10, 20, 44, 11, 12, 11, 8, 12,  11, 22, 21, 18, 21, 18), 
              income = c(35, 72, 11, 35, 37, 36, 33,  70, 34, 74, 70, 44, 76, 70), 
              group = c("case", "case", "case", "case", "control", "control", 
                        "control", "control", "control", "control", "control", 
                        "control", "control", "control")), 
         row.names = c(NA, -14L), class = c("tbl_df", "tbl", "data.frame"))

> dat
# A tibble: 14 x 4
      id   age income group  
   <dbl> <dbl>  <dbl> <chr>  
 1     1    10     35 case   
 2     2    20     72 case   
 3     3    44     11 case   
 4     4    11     35 case   
 5   111    12     37 control
 6   222    11     36 control
 7   333     8     33 control
 8   444    12     70 control
 9   555    11     34 control
10   666    22     74 control
11   777    21     70 control
12   888    18     44 control
13   999    21     76 control
14  1000    18     70 control

预期结果

对于id = 1,匹配的控件如下,我只需要controls在下表中随机选择 2 即可。

|id|age|income|group|
|:----|:----|:----|:----|
|111|12|37|control|
|222|11|36|control|
|333|8|33|control|
|555|11|34|control|

对于id = 2,匹配的控件如下,我只需要controls在下表中随机选择2。

|id|age|income|group|
|:----|:----|:----|:----|
|666|22|74|control|
|777|21|70|control|
|1000|18|70|control|

对于id = 3, 中没有匹配controlsdat

对于id = 4,匹配的控件如下,我只需要controls在下表中随机选择 2 即可。

这里要注意的一件事是,我们可以发现控件id = 1id = 4具有重叠的部分。我不希望两个cases共享一个control,我需要的是如果id = 1选择id = 111id = 222作为control,那么id = 4只能选择id = 555作为control,如果id = 1选择id = 111id = 333作为控制,那么id = 4只能选择id = 222id = 555作为控制。

|id|age|income|group|
|:----|:----|:----|:----|
|111|12|37|control|
|222|11|36|control|
|555|11|34|control|

最终的输出可能是这样的(idin组是从满足条件control的中随机选择的):id

|id|age|income|group|
|:----|:----|:----|:----|
|1|10|35|case|
|2|20|72|case|
|3|44|11|case|
|4|11|35|case|
|111|12|37|control|
|222|11|36|control|
|333|8|33|control|
|555|11|34|control|
|777|21|70|control|
|1000|18|70|control|

笔记

我查了一些网站,但它们不符合我的需求。我不知道如何使用 R 代码实现我的要求。

任何帮助将不胜感激!

参考:

1.https://stackoverflow.com/questions/56026700/is-there-any-package-for-case-control-matching-individual-1n-matching-in-rn

2. R(或spss)中的病例对照匹配,基于年龄、性别和种族?

3.使用 ccoptimalmatch 包在 R 中匹配大小写控制

4. R 中的精确匹配

标签: rdplyrtidyverse

解决方案


在不同的数据框中分离案例和控制。对于中的每一行,在case_data其中找到匹配的行control_data并从中选择 2 个随机行。

使用map_df我们可以将所有内容组合在一个数据框中。

library(dplyr)
library(purrr)

case_data <- dat %>% filter(group == 'case')
control_data <- dat %>% filter(group == 'control')

case_data %>%
  group_split(row_number(), .keep = FALSE) %>%
  map_df(~bind_rows(.x, control_data %>% 
                    filter(between(age, .x$age - 2, .x$age + 2), 
                           between(income, .x$income - 2, .x$income + 2)) %>%
        slice_sample(n = 2)))

#     id   age income group  
#  <dbl> <dbl>  <dbl> <chr>  
#1     1    10     35 case   
#2   333     8     33 control
#3   111    12     37 control
#4     2    20     72 case   
#5   666    22     74 control
#6   777    21     70 control

推荐阅读