在数据框中的分隔符处拆分列[重复]

Posted

技术标签:

【中文标题】在数据框中的分隔符处拆分列[重复]【英文标题】:Split column at delimiter in data frame [duplicate] 【发布时间】:2011-10-27 11:58:15 【问题描述】:

我想在基于分隔符的数据框中将一列分成两列。例如,

a|b
b|c

成为

a    b
b    c

在数据框内。

谢谢!

【问题讨论】:

相关:***.com/questions/7033187/sets-in-r-dataframe/… 【参考方案1】:

@Taesung Shin 是对的,但只需更多的魔法就可以将其变成data.frame。 我添加了一个“x|y”行以避免歧义:

df <- data.frame(ID=11:13, FOO=c('a|b','b|c','x|y'))
foo <- data.frame(do.call('rbind', strsplit(as.character(df$FOO),'|',fixed=TRUE)))

或者,如果您想替换现有 data.frame 中的列:

within(df, FOO<-data.frame(do.call('rbind', strsplit(as.character(FOO), '|', fixed=TRUE))))

产生:

  ID FOO.X1 FOO.X2
1 11      a      b
2 12      b      c
3 13      x      y

【讨论】:

如果它是预先存在的包含 100 列的大型数据框中的一列,您会怎么做? 好问题。我会进行拆分,将其制成一个数据框,适当地重命名它(reshape 包中的rename 函数可以方便地即时执行此操作),然后将rbind 与现有数据框一起使用——额外的努力使它插入到前一列而不是作为第一列或最后一列... 我的更新版本也处理了数百个其他列。 +1 这是最通用的解决方案。它甚至可以处理由“|”分隔的不同数量的值的情况。当然,必须处理 rbind 的结果,它可能会回收那些元素较少的行。但是对于这种情况,另一种解决方案会失败。​​ 小心,length(strsplit('a|', '|', fixed=TRUE))1 -- 如the docs 说:“...但是如果字符串末尾有匹配,则输出与比赛被删除。”正如@YuShen 所说,这个解决方案将“回收”。对我来说,我只想要空的空间,而不是回收。【参考方案2】:

新近流行的tidyr 包使用separate 实现了这一点。它使用正则表达式,因此您必须转义 |

df <- data.frame(ID=11:13, FOO=c('a|b', 'b|c', 'x|y'))
separate(data = df, col = FOO, into = c("left", "right"), sep = "\\|")

#   ID left right
# 1 11    a     b
# 2 12    b     c
# 3 13    x     y

虽然在这种情况下,默认值足够聪明,可以正常工作(它会查找要拆分的非字母数字字符)。

separate(data = df, col = FOO, into = c("left", "right"))

【讨论】:

乍一看这看起来很酷,但是如何将结果重新组合到数据框中? @FlorinAndrei separate 返回一个数据框。不需要额外的工作。【参考方案3】:

Hadley 有一个非常优雅的解决方案,可以在他的 reshape 包中的数据框中执行此操作,使用函数 colsplit

require(reshape)
> df <- data.frame(ID=11:13, FOO=c('a|b','b|c','x|y'))
> df
  ID FOO
1 11 a|b
2 12 b|c
3 13 x|y
> df = transform(df, FOO = colsplit(FOO, split = "\\|", names = c('a', 'b')))
> df
  ID FOO.a FOO.b
1 11     a     b
2 12     b     c
3 13     x     y

【讨论】:

有没有一种方法可以在没有结果列名的情况下得到这个结果,如“FOO.a”和“FOO.b”,但就像“a”和“b”一样(很容易改变,但只是想知道...)? 您可以执行以下操作with(df, cbind(ID, colsplit(df$FOO, pattern = "\\|", names = c('a', 'b'))))。请注意,reshape2 中的参数split 已重命名为pattern,这是reshape 包的更新版本。 我的编辑目前被阻止...我会在每次分配后更新您的答案以打印 df... require(reshape) > df df ID FOO 1 11 a|b 2 12 b|c 3 13 x|y > df = transform(df, FOO = colsplit(FOO, split = "\\|", names = c('a', 'b'))) > df ID FOO.a FOO.b 1 11 ab 2 12 bc 3 13 xy 另外,如果您不知道会产生的列数,有没有办法做到这一点? 这个解决方案的小问题。它将列拆分为“嵌套”数据框,因此如果您需要使用 ggplot2 将数据用于绘图,则无法识别列名。我发现tidyr 中的separate 函数对此目的更有用。查看@Gregor的回答【参考方案4】:

刚刚遇到这个问题,因为它链接在a recent question on SO。

无耻的回答:使用我的“splitstackshape”包中的cSplit

df <- data.frame(ID=11:13, FOO=c('a|b','b|c','x|y'))
library(splitstackshape)
cSplit(df, "FOO", "|")
#   ID FOO_1 FOO_2
# 1 11     a     b
# 2 12     b     c
# 3 13     x     y

即使每列有不同的分隔符,这个特定的函数也可以处理拆分多列:

df <- data.frame(ID=11:13, 
                 FOO=c('a|b','b|c','x|y'), 
                 BAR = c("A*B", "B*C", "C*D"))
cSplit(df, c("FOO", "BAR"), c("|", "*"))
#   ID FOO_1 FOO_2 BAR_1 BAR_2
# 1 11     a     b     A     B
# 2 12     b     c     B     C
# 3 13     x     y     C     D

本质上,它是使用read.table(text = some_character_vector, sep = some_sep) 并将输出绑定到原始data.frame 的精美便捷包装器。换句话说,另一种基本 R 方法可能是:

df <- data.frame(ID=11:13, FOO=c('a|b','b|c','x|y'))
cbind(df, read.table(text = as.character(df$FOO), sep = "|"))
  ID FOO V1 V2
1 11 a|b  a  b
2 12 b|c  b  c
3 13 x|y  x  y

【讨论】:

我特别喜欢你不必定义数据“进入”的列名 同意 tospig。我也喜欢原生方法 read.table(c('a|b','c|d'), '|') 如果我们正在创建一个新的 data.frame 可以解决问题,即使 SO 谈到“在 [现有] 数据框架内”。 read.table 的缺点,sep 只能是一个字节,hash 分隔符被解释为注释? read.table(text=c('a#b'), sep='#') 只产生一列——我期望两列。 @TheRedPea,现在在手机上,但您不能通过将read.table 中的注释字符也指定为"" 来获得您想要的结果吗? @AnandaMahto 你是绝对正确的;这会产生 2 列:read.table(text=c('a#b'), sep='#', comment.char = '') 和单字符分隔符,如果我将 c('a~~b') 传递给 gsub,我可以获得我需要的单字节分隔符:gsub('~~','~', c('a~~b'))【参考方案5】:
strsplit(c('a|b','b|c'),'|',fixed=TRUE)

【讨论】:

【参考方案6】:

结合@Ramnath 和@Tommy 的答案让我找到了一种在base R 中适用于一个或多个列的方法。

基本用法:

> df = data.frame(
+   id=1:3, foo=c('a|b','b|c','c|d'), 
+   bar=c('p|q', 'r|s', 's|t'), stringsAsFactors=F)
> transform(df, test=do.call(rbind, strsplit(foo, '|', fixed=TRUE)), stringsAsFactors=F)
  id foo bar test.1 test.2
1  1 a|b p|q      a      b
2  2 b|c r|s      b      c
3  3 c|d s|t      c      d

多列:

> transform(df, lapply(list(foo,bar),
+ function(x)do.call(rbind, strsplit(x, '|', fixed=TRUE))), stringsAsFactors=F)
  id foo bar X1 X2 X1.1 X2.1
1  1 a|b p|q  a  b    p    q
2  2 b|c r|s  b  c    r    s
3  3 c|d s|t  c  d    s    t

更好地命名多个拆分列:

> transform(df, lapply(l<-list(foo,bar);names(l)=c('foo','bar');l, 
+                          function(x)do.call(rbind, strsplit(x, '|', fixed=TRUE))), stringsAsFactors=F)
  id foo bar foo.1 foo.2 bar.1 bar.2
1  1 a|b p|q     a     b     p     q
2  2 b|c r|s     b     c     r     s
3  3 c|d s|t     c     d     s     t

【讨论】:

以上是关于在数据框中的分隔符处拆分列[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何提取/拆分数据框中的列表列以分隔唯一列?

如何拆分对象列表以分隔pyspark数据框中的列

PowerBI将分隔列拆分为重复行

拆分由空白字符分隔的数字列。

将数据框中的结构类型列拆分为多列

通过分隔符将列文本拆分为R中的多个不同列