【问题标题】:Splitting a column in a data frame by an nth instance of a character按字符的第 n 个实例拆分数据框中的列
【发布时间】:2018-11-28 20:12:30
【问题描述】:

我有一个包含多列的数据框,其中一列由管道“|”填充以及我试图获取的信息。

例如:

View(Table$Column)
"|1||KK|12|Gold||4K|"
"|1||Rst|E|Silver||13||"
"|1||RST|E|Silver||18||"
"|1||KK|Y|Iron|y|12||"
"|1||||Copper|Cpr|||E"
"|1||||Iron|||12|F"

以此类推,大约有 120K 行。 我要挖掘的是这个系列中第 5 根管子和第 6 根管子之间的所有东西,但是在它自己的列向量中,所以最终结果如下所示:

View(Extracted)
Gold
Silver
Silver
Iron
Copper
Iron

我不想使用正则表达式。我的工具在这里仅限于 R。你们有什么建议可以解决这个问题吗?

谢谢。

【问题讨论】:

    标签: r dataframe split dplyr character


    【解决方案1】:

    1) 假设 x 在注释中可重现地定义,最后使用 read.table,如图所示。没有使用正则表达式或包。

    read.table(text = Table$Column, sep = "|", header = FALSE, 
      as.is = TRUE, fill = TRUE)[6]
    

    给予:

          V6
    1   Gold
    2 Silver
    3 Silver
    4   Iron
    5 Copper
    6   Iron
    

    2) 这个替代方案确实使用了正则表达式(问题要求不要这样做),但以防万一这是一个更简洁的解决方案。请注意,它需要 tidyr 0.8.2 或更高版本,因为早期版本的 tidyr 不支持 into= 参数中的 NA

    library(dplyr)
    library(tidyr)
    
    Table %>% 
      separate(Column, into = c(rep(NA, 5), "commodity"), sep = "\\|", extra = "drop")
    

    给予:

      commodity
    1      Gold
    2    Silver
    3    Silver
    4      Iron
    5    Copper
    6      Iron
    

    3) 这是另一种基本解决方案。考虑到 (1) 简单得多,这可能不是您想要的,但我想看看我们是否可以在 base 中提出第二种不使用正则表达式的方法。请注意,如果strsplitsplit= 参数是"",那么它会被特殊处理,因此不是正则表达式。它创建一个列表,其中每个组件都是单个字符的向量。每个这样的向量都被传递给匿名函数,该函数标记| 以及它后面的字段中的字符及其序号。然后我们取出对应于 5 的字符(除了第一个,因为它是 |)并使用 paste 将它们折叠在一起。

    data.frame(commodities = sapply(strsplit(Table$Column, ""), function(chars) {
      wx <- which(cumsum(chars == "|") == 5)
      paste(chars[seq(wx[2], tail(wx, 1))], collapse = "")
    }), stringsAsFactors = FALSE)
    

    给予:

      commodities
    1        Gold
    2      Silver
    3      Silver
    4        Iron
    5      Copper
    6        Iron
    

    注意

    Table <- data.frame(Column = c("|1||KK|12|Gold||4K|",
      "|1||Rst|E|Silver||13||",
      "|1||RST|E|Silver||18||",
      "|1||KK|Y|Iron|y|12||",
      "|1||||Copper|Cpr|||E",
      "|1||||Iron|||12|F"), stringsAsFactors = FALSE)
    

    【讨论】:

      【解决方案2】:

      你可以试试这个:

      df <- data.frame(x = c("|1||KK|12|Gold||4K|", "|1||Rst|E|Silver||13||"), stringsAsFactors = FALSE)
      library(stringr)
      stringr::str_split(df$x, "\\|", simplify = TRUE)[, 6]
      

      【讨论】:

        【解决方案3】:

        1)我们可以在分隔符|上使用strsplit from base R,并从vectors的list中提取第6个元素

        sapply(strsplit(Table$Column, "|", fixed = TRUE), `[`, 6)
        #[1] "Gold"   "Silver" "Silver" "Iron"   "Copper" "Iron"
        

        2)或者使用regex(同样来自base R),使用sub提取第6个单词

        sub("^([|][^|]+){4}[|]([^|]*).*", "\\2", 
               gsub("(?<=[|])(?=[|])", "and", Table$Column, perl = TRUE))
        #[1] "Gold"   "Silver" "Silver" "Iron"   "Copper" "Iron"  
        

        数据

        Table <- structure(list(Column = c("|1||KK|12|Gold||4K|", 
         "|1||Rst|E|Silver||13||", 
         "|1||RST|E|Silver||18||", "|1||KK|Y|Iron|y|12||", "|1||||Copper|Cpr|||E", 
         "|1||||Iron|||12|F")), class = "data.frame", row.names = c(NA, 
         -6L))  
        

        【讨论】:

          猜你喜欢
          • 2016-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-17
          • 2011-05-07
          • 1970-01-01
          相关资源
          最近更新 更多