r 匹配两个数据框中的数据,然后检查另一列中的文本是否匹配行

r match data in two data frames then check text in another column for matched row

我有两个数据帧stu1和stu2。两者都有匹配的 ID 列,但其他列中的变量不同。

例如,stu1:

ID, Grade, Group, Age
ad1, A, Green, 14
bc1, B, Green, 13
cd1, B, Blue, 14
fs3, C, Red, 13

stu2:

ID, Prog, Loc, Year
bc1, LSC1, Ext, 2013
cd1, LSC1, Ext, 2013
cd1, BSC1, Int, 2013
ad1, BSC2, Int, 2012
rs2, KHL4, Ext, 2014

我想做的是检查 stu1 中的学生 ID 是否存在于 stu2 中,然后检查相应行的另一列中的文本是否与我的字符串匹配,例如Prog =='BSC*' 然后在 stu1 中创建一个新列,其中显示 "Yes" 或 "No"。

所以,stu1 的结果应该是:

ID, Grade, Group, Age, BSCProg
ad1, A, Green, 14, Yes
bc1, B, Green, 13, No
cd1, B, Blue, 14, Yes
fs3, C, Red, 13, No

我尝试了很多不同的方法都没有成功,例如:

stu1$BSCProg <- ifelse(stu2[grepl("BSC", stu2$Prog) & match(paste0(stu1$ID), 
    paste0(stu1$ID)),], "Yes", "No")

stu1$BSCProg <- ifelse(is.na(match(paste0(stu1$ID),
    paste0(stu2$ID) & stu2[grepl("BSC", stu2$Prog),])),"No","Yes")

stu1$BSCProg <- ifelse(stu1$ID %in% stu2$ID & grepl('BSC', stu2$Prog), "Yes", "No")

您可以先 merge ID,然后再创建新的列。这是一个 data.table 解决方案:

 library(data.table)
 setDT(stu1, key="ID")
 setDT(stu2, key="ID")
 stu1 = merge(stu1, stu2, all.x=TRUE)
 stu1[, BSCProg:=ifelse(grepl("^BSC", Prog), "Yes", "No")]

我会通过合并两个表来完成此操作,以便您可以进行列比较。使用 data.table:

library(data.table)

setDT(stu1)
setDT(stu2)

dat <- merge(stu1,
             stu2[Prog %like% "BSC", .(ID, BSCProg = Prog)],
             by = "ID",
             all.x = TRUE)

dat[, BSCProg := ifelse(is.na(BSCProg), "No", "Yes")]

结果:

#     ID Grade Group Age BSCProg
# 1: ad1     A Green  14     Yes
# 2: bc1     B Green  13      No
# 3: cd1     B  Blue  14     Yes
# 4: fs3     C   Red  13      No

稍微解压一下,第一步是将 stu2 中的 IDProg 列合并到 stu1 中。 Prog %like% "BSC" 部分将仅合并那些 Prog 列具有 "BSC" 作为值的一部分的行。 BSCProg = Prog最后就是把列重命名为你想要的。

完成后,该列的值将是 NA 或类似 BSC1BSC2 的值。最后的语句 BSCProg := ifelse(is.na(BSCProg), "No", "Yes") 会将任何 NA 更改为 "No" 并将其他任何内容更改为 "Yes".

一个dplyrtidyr的解决方案。 stu3 是最终输出。

library(dplyr)
library(tidyr)

stu1 <- data_frame(ID = c("ad1", "bc1", "cd1", "fs3"),
                   Grade = c("A", "B", "B", "C"),
                   Group = c("Green", "Green", "Blue", "Red"),
                   Age = c(14, 13, 14, 13))

stu2 <- data_frame(ID = c("bc1", "cd1", "cd1", "ad1", "rs2"),
                   Prog = c("LSC1", "LSC1", "BSC1", "BSC2", "KHL4"),
                   Loc = c("Ext", "Ext", "Int", "Int", "Ext"),
                   Year = c(2013, 2013, 2013, 2012, 2014))


stu3 <- stu1 %>%
  full_join(stu2 %>% select(ID, Prog), by = "ID") %>%
  mutate(BSCProg = ifelse(grepl("BSC", Prog), "Yes", "No")) %>%
  drop_na(Grade) %>%
  select(-Prog) %>%
  group_by(ID) %>%
  arrange(desc(BSCProg)) %>%
  slice(1)