【问题标题】:number of items to replace is not a multiple of replacement length error要替换的项目数不是替换长度错误的倍数
【发布时间】:2020-08-21 21:28:07
【问题描述】:

我有一个地址向量(一个小的 sn-p 如下所示)

df=c("westmoorings east","chaguanas proper","bloody bay" ,"westmooorings",   
"el doraldo","rousillac34") (full length=5432)

以及参考城市/地区的另一个向量(参见下面的 sn-p)

areas=c("arima","port of spain","chaguanas") (full length=20)

我想将df 中的地址按areas 向量中的区域分组,例如地址chaguanas proper 将分组在chaguanas 下。我正在使用列表来存储结果。我用来完成此操作的代码是:

L=list() 
for(i in 1:length(areas)){
    ind=grep(paste(areas[i]),df)
    L[i]=df[ind] 
    df[-ind] #updates the df to exclude all addresses already stored in L[i]

}

问题在于 L[i]=df[ind] 行。我收到错误“number of items to replace is not a multiple of replacement length”有人可以帮忙吗?我正在让模式匹配工作,但将结果存储在列表组件中会引发该错误。顺便说一句,我正在使用 R。

【问题讨论】:

  • 如果没有匹配,则 grep 返回 NULL 或 numeric(0)。我猜你需要if/else

标签: r regex list pattern-matching


【解决方案1】:

在您的代码稍作改动后,我建议这样做:

#Data
df=c("westmoorings east","chaguanas proper","bloody bay" ,"westmooorings",
     "el doraldo","rousillac34")
areas=c("arima","port of spain","chaguanas")
#Code
L=list() 
for(i in 1:length(areas)){
  ind=which(grepl(paste(areas[i]),df))
  if(length(ind)!=0)
  {
    L[i]=df[ind]
    df[-ind] 
  }
}

输出:

L

[[1]]
NULL

[[2]]
NULL

[[3]]
[1] "chaguanas proper"

【讨论】:

    【解决方案2】:

    我认为在这里使用sapply 会更容易:

    L <- sapply(areas, function(x) grep(x, df, value = TRUE))
    L
    
    #$arima
    #character(0)
    
    #$`port of spain`
    #character(0)
    
    #$chaguanas
    #[1] "chaguanas proper"
    

    同样使用tidyverse 函数将是:

    purrr::map(areas, ~stringr::str_subset(df, .x))
    

    【讨论】:

      【解决方案3】:

      我们可以使用“areas”的length 预初始化“L”,并像在 cmets 中一样使用if 条件

      L <- vector("list", length(areas))
      for(i in seq_along(areas)){
        ind <-  grep(areas[i],df )
        if(length(ind) > 0) {
          L[[i]]  <- df[ind]
           df <- df[-ind] 
        }
      }
      
      
      L
      #[[1]]
      #NULL
      
      #[[2]]
      #NULL
      
      #[[3]]
      #[1] "chaguanas proper"
      

      注意:这回答了 OP 发布的问题


      如果我们想采用这种矢量化方式,一个非常简单的选择是(没有循环,grep 只被调用一次)

      grep(paste(areas, collapse="|"), df, value = TRUE)
      #[1] "chaguanas proper"
      

      数据

      df <- c("westmoorings east","chaguanas proper","bloody bay" ,"westmooorings",
           "el doraldo","rousillac34")
      areas <- c("arima","port of spain","chaguanas")
      

      【讨论】:

        【解决方案4】:

        您看到的 R 错误经常发生在您的索引语法稍有错误时。在这种情况下,您似乎想要遍历区域向量的元素,但在原始代码中,您要求 R 将返回值放在列表 "L" 的(上)“索引”级别,即L[i]。实际上,您应该将返回值放在列表“L”的(较低)“值”级别,即L[[i]]。查看示例:

        > Output_listA <- list() 
        > for(i in 1:length(areas)){
             Output_listA[[i]] <- grep(areas[i],df, value=TRUE)
             }
        > Output_listA
        [[1]]
        character(0)
        
        [[2]]
        character(0)
        
        [[3]]
        [1] "chaguanas proper"
        

        在 Output_listA 中,您可以看到 grep() 与参数“value=TRUE”一起使用。这将返回匹配列表。但也许你只是想要一个索引来做进一步的操作?然后使用grepl()如下:

        > Output_listB <- list() 
        > for(i in 1:length(areas)){
             Output_listB[[i]] <- grepl(areas[i],df)
             }
        > Output_listB
        [[1]]
        [1] FALSE FALSE FALSE FALSE FALSE FALSE
        
        [[2]]
        [1] FALSE FALSE FALSE FALSE FALSE FALSE
        
        [[3]]
        [1] FALSE  TRUE FALSE FALSE FALSE FALSE
        
        > df[ Output_listB[[3]] ]
        [1] "chaguanas proper"
        

        最后,您可以让lapply() 函数为您完成工作。下面显示了grep() 的使用,但您也可以轻松使用grepl()

        > lapply(areas, FUN = function(x) grep(x, df, value=TRUE) )
        [[1]]
        character(0)
        
        [[2]]
        character(0)
        
        [[3]]
        [1] "chaguanas proper"
        

        【讨论】:

          猜你喜欢
          • 2021-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-05
          • 1970-01-01
          相关资源
          最近更新 更多