我从excel电子表格中读取了一些数据,其中策展人不了解关系数据库并处理1-many关系,因此将多个变量放在一列中:
>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
列转换为新数据框,以便我可以拥有1-many关系:
>df
id var2
X1 X1 1
X23 X23 2
X5 X5 3
>df2
id var
1 X1 foo
2 X1 bar
3 X1 hello
4 X23 world
我能够将vars
列解析为一个列表,其中每个条目都是变量的向量:
>library(stringr)
>halfway <- str_split(df$vars, pattern=", ")
>halfway
[[1]]
[1] "foo" "bar" "hello"
[[2]]
[1] "world"
[[3]]
[1] NA
但我不确定如何获取此列表并将其转换为较长的data.frame
。
我有一个游戏,但我不能把它变成长格式而不会丢失每个变量所属的ID的信息(使用unlist
)。
我也看了reshape
,但它似乎没有做我想要的。
我可以使用for循环来迭代地构建新表,但这非常低效。对此有优雅的解决方案吗?
答案 0 :(得分:2)
这可以通过data.table
包以非常简单的方式完成:
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")]
答案 1 :(得分:2)
concat.split.multiple
有一个选项来执行拆分并一步完成整形,只剩下删除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
other scenarios has fared quite well函数{{3}}关于速度的“胆量”。我从未对此特定功能进行基准测试(主要是因为我从未真正处理过非常大的数据集)。
答案 2 :(得分:1)
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]]))
和do.call
将结果列表元素绑定到单个数据框中:
df2 <- do.call(rbind,threequarterway)
最后,像David Robinson的回答一样摆脱NA行:
df2 = df2[!is.na(df2[,2]),]
(大卫的答案出现在我打字的时候,可能是一种更好的方法,但我认为你可能想知道expand.grid
无论如何。)