【问题标题】:Creating several new vectors from an original vector with separators使用分隔符从原始向量创建几个新向量
【发布时间】:2019-02-13 15:56:04
【问题描述】:

我正在尝试从原始向量创建多个向量。 我阅读了一些帖子,但找不到解决问题的方法。

我的原始向量是这样的:

> orig_vec
[1] "A"  "B"  "C"  "D;" "1"  "2;" "a1" "a2" "a3"

我想要看起来像这样的向量:

> vector1
[1] "A" "B" "C" "D"
> vector2
[1] "1" "2"
> vector3
[1] "a1" "a2" "a3"

所以我需要一个将分号识别为分隔符并根据“orig_vec”中分隔值的数量创建新向量的代码。

我也有“orig_vec”可以改变的问题。 当它看起来像这样:

> orig_vec
[1] "A"   "B"   "C"   "D"   "E;"  "1"   "2;"  "a1"  "a2"  "a3;" "b1" 

我需要自动获取这些向量:

> vector1
[1] "A" "B" "C" "D" "E"
> vector2
[1] "1" "2"
> vector3
[1] "a1" "a2" "a3"
> vector4
[1] "b1"

很抱歉,我无法提供更多代码或任何解决方案的想法。

【问题讨论】:

    标签: r


    【解决方案1】:

    这应该可行:

    x <- c("A",  "B",  "C",  "D;", "1",  "2;", "a1", "a2", "a3")
    
    sapply(split(x, c(0, cumsum(grepl(";", x))[-length(x)])), function(x) gsub(";", "", x))
    
    $`0`
    [1] "A" "B" "C" "D"
    
    $`1`
    [1] "1" "2"
    
    $`2`
    [1] "a1" "a2" "a3"
    

    我们使用条件grepl(";", x)cumsum() 来创建一个向量,用于使用split() 进行子集化,然后删除sapply()ing gsub() 的分号。

    【讨论】:

    • 我在意识到你的答案非常接近之前回答了:)。你可以让它更紧凑一点:split(sub(";","",s),cumsum(c(0,head(grepl(";",s),-1))))
    【解决方案2】:

    我也喜欢@LAP,这是另一种选择:

    vec <- c("A", "B", "C", "D;", "1", "2;", "a1", "a2", "a3;", "b1")
    
    ix <- grep(";", vec)
    
    mapply(function(x, ix1, ix2) x[ix1:ix2], 
           x = list(sub(";", "", vec)),
           ix1 = c(1, ix + 1),
           ix2 = c(ix, length(vec)))
    
    [[1]]
    [1] "A" "B" "C" "D"
    
    [[2]]
    [1] "1" "2"
    
    [[3]]
    [1] "a1" "a2" "a3"
    
    [[4]]
    [1] "b1"
    

    您会注意到,大多数人给出的答案都是向量列表,而不是分配给变量名的少数向量。使用对象列表而不是散布在名称空间中的对象通常更干净、更容易。只需增加 $.02 美元。

    【讨论】:

      【解决方案3】:

      这是一种方法,基于先加入一个空间然后连续分裂的想法,首先是;,然后是一个空间:

      s <- c("A",  "B",  "C",  "D;", "1" , "2;" ,"a1", "a2", "a3")
      s <- paste0(s,collapse = ' ')
      s <- unlist(strsplit(s, ';'))
      vectors <- lapply(s,function(x) unlist(strsplit(trimws(x),' ')))
      
      > vectors
      [[1]]
      [1] "A" "B" "C" "D"
      
      [[2]]
      [1] "1" "2"
      
      [[3]]
      [1] "a1" "a2" "a3"
      

      【讨论】:

        【解决方案4】:

        只是引入一种在单个管道中工作的 tidyverse 方法。

        与其他答案类似,将向量折叠成单个字符串,然后在每个 ; 上拆分该字符串。我使用空格作为折叠,以便以后可以轻松使用str_trim

        library(tidyverse)
        
        x %>%
          paste(collapse = " ") %>%
          strsplit(split = ";", fixed = T)
        #> [[1]]
        #> [1] "A B C D E" " 1 2"      " a1 a2 a3" " b1"
        

        由于strsplit 为您提供了一个列表,并且至少在这种情况下,您只对第一个列表条目感兴趣,使用[[ 将其拉出并修剪这些向量的开头和结尾空格。 map 为您提供一个包含每个字符串的向量列表。

        x %>%
          paste(collapse = " ") %>%
          strsplit(split = ";", fixed = T) %>%
          `[[`(1) %>%
          map(str_trim)
        #> [[1]]
        #> [1] "A B C D E"
        #> 
        #> [[2]]
        #> [1] "1 2"
        #> 
        #> [[3]]
        #> [1] "a1 a2 a3"
        #> 
        #> [[4]]
        #> [1] "b1"
        

        然后将每个向量按空格分割,并展平为一个向量列表。

        多合一管道:

        x %>%
          paste(collapse = " ") %>%
          strsplit(split = ";", fixed = T) %>%
          `[[`(1) %>%
          map(str_trim) %>%
          map(str_split, " ") %>%
          flatten()
        #> [[1]]
        #> [1] "A" "B" "C" "D" "E"
        #> 
        #> [[2]]
        #> [1] "1" "2"
        #> 
        #> [[3]]
        #> [1] "a1" "a2" "a3"
        #> 
        #> [[4]]
        #> [1] "b1"
        

        reprex package (v0.2.1) 于 2019 年 2 月 13 日创建

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-30
          相关资源
          最近更新 更多