【问题标题】:Match values by string containing another string按包含另一个字符串的字符串匹配值
【发布时间】:2021-03-28 14:02:17
【问题描述】:

我有两个数据框。第一个看起来像这样:

month     Joanne K. Rowling   Samuel L. Jackson
2000/01   1                   0
2000/02   1                   1
2000/03   0                   1
2000/04   0                   0
2000/05   0                   1
2000/06   1                   0

test_1

另一个是这样的

Name            Score
Samuel Jackson  67
Joanne Rowling  52

test_2

我想将它们组合起来以获得以下数据框

month     Joanne K. Rowling   Samuel L. Jackson
2000/01   52                   0
2000/02   52                   67
2000/03   0                    67
2000/04   0                    0
2000/05   0                    67
2000/06   52                   0

其中值 1 被 test_2 中的分数替换。 test_1 中的 colnames 可能与 table_2 中的值略有不同,因此不应修复匹配。我找到了一种方法:

for(i in 1:nrow(test_2)) {
  for(k in 1:ncol(test_1){
    for(l in 1:nrow(test_1)){
      if(grepl(test_2[i,6],as.data.frame(colnames(test_1))[k,1])) {
        if(test_1[l,k]==1){
          test_1[l,k]<-test_2[i,5]
        }
      }
    }
  }
}

但它的效率非常低,因为我必须将其应用于数据框列表。 请尝试编写一个尽可能少循环的有效方法

【问题讨论】:

    标签: r string-matching


    【解决方案1】:

    我认为grepl 不会直接在这里工作,因为'Joanne Rowling' 不会与'Joanne K. Rowling' 匹配。您可以使用stringdist::stringdistmatrix 来获取匹配项,然后将相应的值相乘。

    mat <- stringdist::stringdistmatrix(names(test_1)[-1], test_2$Name)
    test_1[-1] <- sweep(test_1[-1], 2, test_2$Score[max.col(-mat)], `*`)
    test_1
    
    #    Month Joanne K. Rowling Samuel L. Jackson
    #1 2000/01                52                 0
    #2 2000/02                52                67
    #3 2000/03                 0                67
    #4 2000/04                 0                 0
    #5 2000/05                 0                67
    #6 2000/06                52                 0
    

    要将其应用于多个数据帧,您可以这样做:

    lapply(test_1_list, function(x) {
      mat <- stringdist::stringdistmatrix(names(x)[-1], test_2$Name)
      x[-1] <- sweep(x[-1], 2, test2$Score[max.col(-mat)], `*`)
      x
    }) -> result
    result
    

    test_1_list 是数据帧列表。

    数据

    test_1<-data.frame("Month"=c("2000/01","2000/02","2000/03","2000/04","2000/05","2000/06"),
                       "Joanne K. Rowling"=c(1,1,0,0,0,1),
                       "Samuel L. Jackson"=c(0,1,1,0,1,0), check.names = FALSE)
    test_2<-data.frame("Name"=c("Samuel Jackson","Joanne Rowling"),"Score"=c(67,52))
    

    【讨论】:

      【解决方案2】:

      您可以使用replace 函数并定义一个索引向量来决定应替换哪些值:

      # Just for JK Rowling
      test_1[,2] <- replace(test_1[,2], test_1[,2] == 1, test_2[2,2])
      

      test_1[,2] == 1 创建一个索引向量,TRUE 代表 1,FALSE 代表 0。

      这样就可以为 Samuel Jackson 复制该行。

      【讨论】:

      • 感谢您的输入,但我的名字远不止这些,因此为每个人创建一行是不切实际的。
      猜你喜欢
      • 1970-01-01
      • 2012-10-05
      • 2019-04-24
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 2021-08-17
      • 2011-08-31
      • 1970-01-01
      相关资源
      最近更新 更多