在R中将1-many列解析为新data.frame的优雅方法

在R中将1-many列解析为新data.frame的优雅方法,r,reshape,R,Reshape,我从excel电子表格中读取了一些数据,其中策展人不知道关系数据库和处理1-多个关系,因此将多个变量放在一列中: >df <- data.frame(id=c("X1", "X23", "X5"), vars=c("foo, bar, hello", "world", NA), var2=c(1,2,3)) >df id vars var2 1 X1 foo, bar, hello 1 2 X23 world 2 3

我从excel电子表格中读取了一些数据,其中策展人不知道关系数据库和处理1-多个关系,因此将多个变量放在一列中:

>df <- data.frame(id=c("X1", "X23", "X5"), vars=c("foo, bar, hello", "world", NA), var2=c(1,2,3))
>df
   id            vars var2
1  X1 foo, bar, hello    1
2 X23           world    2
3  X5            <NA>    3
我能够将
vars
列解析为一个列表,其中每个条目都是变量向量:

>library(stringr)
>halfway <- str_split(df$vars, pattern=", ")
>halfway
[[1]]
[1] "foo"   "bar"   "hello"

[[2]]
[1] "world"

[[3]]
[1] NA
>库(stringr)
>半路
[[1]]
[1] “foo”“bar”“你好”
[[2]]
[1] “世界”
[[3]]
[1] NA
但我不确定如何将此列表转换为长的
data.frame

我已经尝试过了,但是如果不丢失每个变量所属ID的信息(使用
unlist
),我无法将其转换为长格式。 我还研究了
重塑
,但它似乎没有达到我想要的效果


我可以使用for循环以迭代方式构建新表,但效率非常低。是否有一个优雅的解决方案?

这可以通过使用
数据以非常简单的方式完成。表
包:

library(data.table)
dt = as.data.table(df)
df2 = dt[, list(var=str_split(vars, ", ")[[1]]), by=id]
df2 = df2[!is.na(var), ]
这样做的一个优点是,如果您有多个ID列(例如,ID、id2、id3),您可以将其更改为

df2 = dt[, list(var=strsplit(vars, ", ")[[1]]), by=c("id", "id2", "id3")]

这可以通过使用
数据以非常简单的方式完成。表
包:

library(data.table)
dt = as.data.table(df)
df2 = dt[, list(var=str_split(vars, ", ")[[1]]), by=id]
df2 = df2[!is.na(var), ]
这样做的一个优点是,如果您有多个ID列(例如,ID、id2、id3),您可以将其更改为

df2 = dt[, list(var=strsplit(vars, ", ")[[1]]), by=c("id", "id2", "id3")]

expand.grid
函数通常用于重塑数据。例如:

> expand.grid(df[1,1],halfway[[1]])
  Var1  Var2
1   X1   foo
2   X1   bar
3   X1 hello
您可以使用
apply
对数据框的每一行执行此操作:

threequarterway <- lapply(seq(nrow(df)),function(i) expand.grid(df[i,1],halfway[[i]]))
df2 <- do.call(rbind,threequarterway)
最后,如David Robinson的回答中所述,消除NA争议:

df2 = df2[!is.na(df2[,2]),]

(David的回答是在我键入时出现的,这可能是一种更好的方法,但我想您可能想知道
expand.grid

expand.grid
函数通常对重塑数据有用。例如:

> expand.grid(df[1,1],halfway[[1]])
  Var1  Var2
1   X1   foo
2   X1   bar
3   X1 hello
您可以使用
apply
对数据框的每一行执行此操作:

threequarterway <- lapply(seq(nrow(df)),function(i) expand.grid(df[i,1],halfway[[i]]))
df2 <- do.call(rbind,threequarterway)
最后,如David Robinson的回答中所述,消除NA争议:

df2 = df2[!is.na(df2[,2]),]

(David的回答是在我键入此内容时出现的,可能是一种更好的方法,但我想您可能想知道
扩展.grid

concat.split.multiple
从我的“splitstackshape”包中可以选择一步执行拆分和重塑,只剩下一件事:删除带有
NA
值的行:

library(splitstackshape)
out <- concat.split.multiple(df, "vars", ",", direction = "long")
out[complete.cases(out), ]
#    id var2 time  vars
# 1  X1    1    1   foo
# 2 X23    2    1 world
# 4  X1    1    2   bar
# 7  X1    1    3 hello
库(splitstackshape)

out
concat.split。我的“splitstackshape”软件包中的多个
可以选择一步执行拆分和重塑,只剩下删除带有
NA
值的行:

library(splitstackshape)
out <- concat.split.multiple(df, "vars", ",", direction = "long")
out[complete.cases(out), ]
#    id var2 time  vars
# 1  X1    1    1   foo
# 2 X23    2    1 world
# 4  X1    1    2   bar
# 7  X1    1    3 hello
库(splitstackshape)

谢谢,我得查一下数据表。更多信息!谢谢,我要查看数据表包更多!