匹配多个字符串并加入

时间:2019-01-31 08:14:48

标签: r string join match

我在匹配r中的多个字符串时遇到困难。我拥有的数据框如下所示:

      Var1                                      Var2
1   SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4
2  ODJSMDK   Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4
3 JDKSAKDJ                       PE35RV747;P0F071G1G

我想匹配用“;”分隔的字符串具有以下数据框中的值:

      Var_x    Var_y
1 P04TGI7F3     good
2 P030Y7Y11   normal
3 PE35RV747      bad
4 Q2UKLVVX4   normal

这样生成的数据框看起来像:

      Var1                                      Var2                    Var3
1   SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4  good;normal;bad;normal
2  ODJSMDK   Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4       normal;bad;normal
3 JDKSAKDJ                       PE35RV747;P0F071G1G                     bad

到目前为止,我尝试通过模糊连接来实现:

fuzzy_left_join(Data1, Data2, by = c("Var2"="Var_x"), match_fun = str_detect)

这可以完成工作,但是它占用了大量内存(我的数据集非常大,R停止工作)。我试图通过for循环来做到这一点,但是我不知道该怎么做。有人知道吗?

5 个答案:

答案 0 :(得分:2)

使用基数R,遍历Var2,在";"上分割,然后进行 match

df1$Var3 <- sapply(df1$Var2, function(i){
  paste(df2$Var_y[ match(unlist(strsplit(i, split = ";")), df2$Var_x) ], collapse = ";")
})

#       Var1                                    Var2                   Var3
# 1   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
# 2  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4   normal;NA;bad;normal
# 3 JDKSAKDJ                     PE35RV747;P0F071G1G                 bad;NA

注意:我知道我的输出在Var3中具有NA,而OP的预期输出却没有。但是我更喜欢保留NA,以便我们可以按原始字符串中的位置将每个“坏/正常”匹配到对应的字符串。当然,如果OP愿意,可以使用na.omit将其删除:

df1$Var3 <- sapply(df1$Var2, function(i){
  paste(na.omit(df2$Var_y[ match(unlist(strsplit(i, split = ";")), df2$Var_x) ]), collapse = ";")
})
#       Var1                                    Var2                   Var3
# 1   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
# 2  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4      normal;bad;normal
# 3 JDKSAKDJ                     PE35RV747;P0F071G1G                    bad

答案 1 :(得分:2)

这是一个通过tidyverse的想法。我们分离行,在第二个数据帧上合并,然后再次基于Var1进行连接,

library(tidyverse)

df1 %>% 
 separate_rows(Var2) %>% 
 left_join(df2, by = c('Var2' = 'Var_x')) %>% 
 group_by(Var1) %>% 
 summarise_all(funs(paste(., collapse = ';')))

给出,

# A tibble: 3 x 3
  Var1     Var2                                    Var_y                 
  <fct>    <chr>                                   <chr>                 
1 JDKSAKDJ PE35RV747;P0F071G1G                     bad;NA                
2 ODJSMDK  Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4 normal;NA;bad;normal  
3 SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal

如果您不想包含NAs,我们可以在加入之前省略(如@akrun所述),即

df1 %>% 
 separate_rows(Var2) %>% 
 filter(Var2 %in% df2$Var_x) %>% 
 left_join(df2, by = c('Var2' = 'Var_x')) %>% 
 group_by(Var1) %>% 
 summarise_all(funs(paste(., collapse = ';')))

给出,

# A tibble: 3 x 3
  Var1     Var2                                    Var_y                 
  <fct>    <chr>                                   <chr>                 
1 JDKSAKDJ PE35RV747                               bad                   
2 ODJSMDK  Q2UKLVVX4;PE35RV747;Q2UKLVVX4           normal;bad;normal     
3 SJDJWK   P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal

答案 2 :(得分:2)

data.table

df2[df1[, unlist(tstrsplit(Var2, ";")), Var1], 
    on = .(Var_x = V1)
    ][,
      lapply(.SD, function(x) paste(x[!is.na(x)], collapse = ";")), 
      by = Var1
      ]

       Var1                                   Var_x                  Var_y
1:   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
2:  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4      normal;bad;normal
3: JDKSAKDJ                     PE35RV747;P0F071G1G                    bad

答案 3 :(得分:2)

另一个带有gsubfn的选项,其中我们为list个字符中的replacement中的gsubfn中的{{1} pattern。请注意,在某些情况下, 'df2'。如果所有替换项都在那里,则不需要第二个;(假设在示例中未提供)

gsub

数据

library(gsubfn)
df1$Var_y <-  gsub(";[A-Z0-9]+", "", gsubfn("[^;]+",  
                setNames(as.list(df2$Var_y), df2$Var_x), df1$Var2))
df1
#      Var1                                    Var2                  Var_y
#1   SJDJWK P04TGI7F3;P030Y7Y11;PE35RV747;Q2UKLVVX4 good;normal;bad;normal
#2  ODJSMDK Q2UKLVVX4;PWER00711;PE35RV747;Q2UKLVVX4      normal;bad;normal
#3 JDKSAKDJ                     PE35RV747;P0F071G1G                    bad

答案 4 :(得分:0)

您可以在基本folder1/file1 folder2/file2 中从第二个R构建一个命名向量,然后在拆分之后,我们在该命名向量中查找所有相关值,删除NA并粘贴回去。

data.frame