首页 > 解决方案 > 按字符的第 n 个实例拆分数据框中的列

问题描述

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

例如:

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。你们碰巧有什么建议可以克服这个问题吗?

谢谢你。

标签: rdataframesplitdplyrcharacter

解决方案


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

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 中提出第二种不使用正则表达式的方法。请注意,如果 is 的参数split=则被特殊处理,因此不是正则表达式。它创建一个列表,其中每个组件都是单个字符的向量。每个这样的向量都被传递给匿名函数,该函数用其序号标记字段中的字符和字符。然后我们取对应于 5 的字符(第一个除外),并使用 将它们折叠在一起。strsplit""||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)

推荐阅读