tidyr在多列上使用separate_rows

use*_*413 11 r apply tidyr

我有一个data.frame,其中一些单元格包含逗号分隔值的字符串:

d <- data.frame(a=c(1:3), 
       b=c("name1, name2, name3", "name4", "name5, name6"),
       c=c("name7","name8, name9", "name10" ))
Run Code Online (Sandbox Code Playgroud)

我想将每个名称拆分为自己的单元格的字符串分开.这很容易

tidyr::separate_rows(d, b, sep=",") 
Run Code Online (Sandbox Code Playgroud)

如果一次完成一列.但我不能同时对"b"和"c"这两列执行此操作,因为它要求每个字符串中的名称数相同.而不是写作

tidyr::separate_rows(d, b, sep=",") 
tidyr::separate_rows(d, c, sep=",") 
Run Code Online (Sandbox Code Playgroud)

有没有办法在单行中执行此操作,例如使用apply?就像是

apply(d, 2, separate_rows(...)) 
Run Code Online (Sandbox Code Playgroud)

不知道如何将参数传递给separate_rows()函数.

Ric*_*ven 12

你可以使用管道.请注意,sep = ", "会自动检测到.

d %>% separate_rows(b) %>% separate_rows(c)
#   a     b      c
# 1 1 name1  name7
# 2 1 name2  name7
# 3 1 name3  name7
# 4 2 name4  name8
# 5 2 name4  name9
# 6 3 name5 name10
# 7 3 name6 name10
Run Code Online (Sandbox Code Playgroud)

注意:使用tidyr版本0.6.0,其中%>%运算符包含在包中.


更新:使用@doscendodiscimus注释,我们可以使用for()循环并d在每次迭代中重新分配.这样我们就可以拥有尽可能多的列.我们将使用列名的字符向量,因此我们需要切换到标准评估版本separate_rows_.

cols <- c("b", "c")
for(col in cols) {
    d <- separate_rows_(d, col)
}
Run Code Online (Sandbox Code Playgroud)

这给了更新 d

  a     b      c
1 1 name1  name7
2 1 name2  name7
3 1 name3  name7
4 2 name4  name8
5 2 name4  name9
6 3 name5 name10
7 3 name6 name10
Run Code Online (Sandbox Code Playgroud)

  • @ user23413,你可以尝试像`for(col in c("b","c"))循环d < - separate_rows_(d,col,sep =",")``如果你想坚持`tidyr` (3认同)

mto*_*oto 6

splitstackshape::cSplit这是使用和的替代方法zoo::na.locf

library(splitstackshape)
library(zoo)

df <- cSplit(d, 1:ncol(d), "long", sep = ",")
na.locf(df[rowSums(is.na(df)) != ncol(df),])
#    a     b      c
#1:  1 name1  name7
#2:  1 name2  name7
#3:  1 name3  name7
#4:  2 name4  name8
#5:  2 name4  name9
#6:  3 name5 name10
#7:  3 name6 name10
Run Code Online (Sandbox Code Playgroud)