dplyr для сопоставления регистра и контроля

#r #dataframe #dplyr #match

#r #фрейм данных #dplyr #совпадение

Вопрос:

Я знаком с другими R-пакетами, такими как MatchIt , однако, я в первую очередь ищу a dplyr -решение. Я не пробовал никаких решений, поскольку это превышает мои текущие уровни квалификации.

Допустим, у меня есть две группы пациентов с одним и тем же заболеванием, получающих одно из двух методов лечения. p$group=="A" получено как p$total.ssa и p$total.ev во время p$group=="B" получения p$total.ssa , исключительно.

 > head(p)
  group total.ssa total.ev age WHO
1     A       347     3240  49   3
2     A       347     3240  54   3
3     A       456     4260  62   3
4     A       456     4260  55   3
5     A       163     1520  61   3
6     A       258     2410  55   3
  

Допустим, я хочу создать соответствие 1: 1 p$group=="A" : p$group=="B" . p$group=="A" это группа, которая должна быть сопоставлена p$group=="B" , но критерии должны быть

  • p$age должно быть /- 3, т. Е. У p$group=="B" пациента должен быть p$age максимальный интервал в 3 года по сравнению с p$group=="A" пациентом
  • p$total.ssa должно быть /- 200, т.Е. У p$group=="B" пациента должен быть p$total.ssa максимальный диапазон в 200 лет по сравнению с p$group=="A" пациентом
  • p$WHO должно быть точно таким же
  • Если ввод данных не p$group=="B" может быть выполнен, этот конкретный p$group=="A" пациент должен быть опущен

Ожидаемый результат — это новое data frame , включающее подмножество сопоставленных пациентов между двумя группами p$group=="A" и p$group=="B"

Ожидаемый результат

   group total.ssa       total.ev     age       WHO
1     A       347           3240     49        3
2     B       347 /-200     0        49 /-3    3
3     A       456           4260     62        3
4     B       456 /-200     0        62 /-3    3
5     A       163           1520     61        2
6     B       163 /-200     0        61 /-3    2
  

Мои данные

 p <- structure(list(group = c("A", "A", "A", "A", "A", "A", "A", "A", 
"A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", 
"B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", 
"B", "B", "B", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", 
"A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", 
"B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", 
"B", "B"), total.ssa = c(347, 347, 456, 456, 163, 258, 1000, 
1000, 433, 433, 433, 433, 115, 115, 420, 580, 300, 300, 60, 220, 
60, 180, 220, 100, 100, 100, 220, 180, 180, 220, 60, NA, 60, 
60, 30, 120, 90, 360, 300, 60, 180, 90, 60, 330, 210, 180, 90, 
480, 60, 870, 240, 360, 210, 360, 120, 240, 1080, 270, 690, 870, 
270, 960, 110, 750, 150, 990, 30, 70, NA, 110, 710, 70, 870, 
510, 390), total.ev = c(3240L, 3240L, 4260L, 4260L, 1520L, 2410L, 
9330L, 9330L, 4040L, 4040L, 4040L, 4040L, 1070L, 1070L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 3230L, 205L, 840L, 160L, 3060L, 1920L, 
1470L, 700L, 2140L, 700L, 8160L, 1980L, 3300L, 1680L, 3360L, 
1040L, 2130L, 4950L, 2130L, 6310L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), age = c(49, 54, 62, 55, 
61, 55, 52, 55, 48, 36, 44, 56, 72, 80, 62, 83, 41, 67, 55, 68, 
26, 45, 52, 87, 51, 61, 51, 84, 74, 72, 63, 48, 54, 34, 28, 55, 
31, 47, 56, 65, 75, 55, 70, 48, 40, 60, 36, 30, 43, 54, 43, 70, 
58, 73, 43, 60, 44, 70, 53, 84, 56, 46, 71, 68, 65, 84, 68, 59, 
86, 64, 51, 63, 56, 43, 52), WHO = structure(c(3L, 3L, 3L, 3L, 
3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 1L, 3L, 1L, 3L, 3L, 2L, 
3L, 1L, 1L, 2L, 1L, 1L, 3L, 2L, 1L, 1L, 3L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 3L, 2L, 3L, 2L, 1L, 2L, 3L, 2L, 2L, 2L, 1L, 
3L, 3L, 3L, 2L, 3L, 2L, 3L, 1L, 1L, 1L, 3L, 1L, 1L, 1L, 1L, 2L, 
1L, 1L, 1L, 3L, 2L, 3L, 1L), .Label = c("1", "2", "3", "4"), class = "factor")), row.names = c(NA, 
75L), class = "data.frame")
  

Комментарии:

1. 1) Вы что-нибудь пробовали? 2) У вас есть только две группы? 3) Можете ли вы показать ожидаемый результат для совместно используемых данных.

2. Привет @Ronak. Спасибо за комментарий. Я соответствующим образом обновил свой вопрос: 1) нет, это намного выше моего уровня квалификации, 2) да, только две группы, 3) см. Обновленный вопрос. Заранее благодарю вас. Лучшие

3. Одна строка «A» может соответствовать нескольким строкам «B». Итак, вы хотите сохранить несколько совпадений одной и той же строки в данных?

4. Привет @RonakShah. Спасибо за решение. В вашем решении каждая строка в «A» содержит только одно совпадение строк в «B», а не несколько, верно?

5. Нет, не обязательно. Но если вы хотите это сделать, вы можете добавить ` group_by (row.x) %>% slice (1L)` combine_data .

Ответ №1:

Вы можете попробовать следующее :

 library(dplyr)
#Make 2 separate dataframes
A_data <- p %>% filter(group == 'A') %>% mutate(row = row_number())
B_data <- p %>% filter(group == 'B') %>% mutate(row = row_number())


#Join them by WHO
combine_data <- A_data %>%
  full_join(B_data, by = 'WHO') %>%
  filter(abs(age.x - age.y) <= 3, abs(total.ssa.x - total.ssa.y) <= 200)

#Get the row index and slice individual data
A_data %>%
  slice(combine_data$row.x) %>%
bind_rows(B_data %>%
  slice(combine_data$row.y)) %>%
  #This is just to rearrange the data for viewing the rows in pairs
  slice(c(rbind(1:(n()/2), ((n()/2) 1):n())))

#   group total.ssa total.ev age WHO row
#1      A       347     3240  49   3   1
#2      B       220        0  51   3  13
#3      A       347     3240  54   3   2
#4      B       220        0  51   3  13
#5      A       163     1520  61   3   5
#6      B        60        0  63   3  17
#7      A       163     1520  61   3   5
#8      B        70        0  63   3  38
#9      A       258     2410  55   3   6
#10     B        60        0  55   3   5
#...
#...