我正在尝试“自动”将data.frame列转换为多列。
这是df的样子:
library(dplyr)
foo <- data_frame(ID = c(1,2),
Val = c("A", "B"),
Geom = c("[{X11,Y11,Z11}, {X12,Y12,Z12}, {X13,Y13,Z13}]", "[{X21,Y21,Z21},{X22,Y22,Z22},{X23,Y23,Z23}]"))
这就是我希望它的样子:
bar <- data_frame(ID = c(1,1,1,2,2,2),
Val=c("A", "A", "A", "B", "B", "B"),
Geom1 = c("X11", "X12", "X13", "X21", "X22", "X23"),
Geom2 = c("Y11", "Y12", "Y13", "Y21", "Y22", "Y23"),
Geom3 = c("Z11", "Z12", "Z13", "Z21", "Z22", "Z23"))
我考虑进行这种转换的工作流程包括两部分:
1 - 将Geom转换为R结构,如:
list(c("X11","Y11","Z11"), c(...), ...)
2 - 使用tidyr::unnest()
或tidyr::separate()
将此类列表拆分为列
我想我可以处理第二部分,但找不到第一部分的好指针。我可以将此列写入csv并在之后自动读取,但考虑到我的data.frame将是一个闪亮的反应对象,这将涉及大量的写/读。
我尝试使用fromJSON()
(jsonlite,rjson和RJSONIO),但因为这不是有效的json-string,所以它不解析它。
答案 0 :(得分:4)
data.table
/ splitstackshape
的解决方案:
library(data.table)
library(splitstackshape)
dt = setDT(foo)[,strsplit(gsub('\\[{|}\\]','', Geom, perl=T), '}, *{', perl=T), .(ID, Val)]
cSplit(dt, 'V1')
# ID Val V1_1 V1_2 V1_3
#1: 1 A X11 Y11 Z11
#2: 1 A X12 Y12 Z12
#3: 1 A X13 Y13 Z13
#4: 2 B X21 Y21 Z21
#5: 2 B X22 Y22 Z22
#6: 2 B X23 Y23 Z23
答案 1 :(得分:2)
这是使用基数R的一种方法:
# vector to work with
geom <- c("[{X11,Y11,Z11}, {X12,Y12,Z12}, {X13,Y13,Z13}]", "[{X21,Y21,Z21},{X22,Y22,Z22},{X23,Y23,Z23}]")
# remove extraneous characters and split into list using "},"
geom <- strsplit(gsub("[]{ []", "", Geom), split="},")
# remove two "}"s
geom <- sapply(geom, function(i) gsub("}", "", i))
# make a list of elements
geom <- strsplit(geom, split=",")
# construct the variables
geomData <- data.frame(t(sapply(geom, function(i) sapply(1:3, function(row) c(i[row])))))
# give names to data frame
names(geomData) <- c("Geom1", "Geom2", "Geom3")
# final data.frame
fooNew <- cbind(foo[, 1:2], geomData)
答案 2 :(得分:1)
1)dplyr 这会将数据框拆分为行,并且每行都会使用gsub
将每个三元组拆分为一个单独的行,并read.table
解析{{1} }} 进一步。然后它修复列名称并执行Geom
。 (如果V1,V2和V3为OK而不是Geom1,Geom2和Geom3,则ungroup
行可以省略。)
setNames
,并提供:
library(dplyr)
foo %>%
group_by(ID, Val) %>%
do(read.table(text=gsub("^..|..$|}, *{", "\n", .$Geom, perl=T), sep=",", as.is=T)) %>%
setNames(sub("^V(\\d+)", "Geom\\1", colnames(.))) %>%
ungroup()
2)没有软件包这使用相同的方法,但没有任何软件包。如果V1,V2,V3是OK而不是Geom1,Geom2和Geom3,则可以省略最后一行代码。
Source: local data frame [6 x 5]
ID Val Geom1 Geom2 Geom3
(dbl) (chr) (chr) (chr) (chr)
1 1 A X11 Y11 Z11
2 1 A X12 Y12 Z12
3 1 A X13 Y13 Z13
4 2 B X21 Y21 Z21
5 2 B X22 Y22 Z22
6 2 B X23 Y23 Z23
,并提供:
bar <- do.call("rbind", by(foo, foo$ID, function(x)
cbind(x[1:2], read.table(text = gsub("^..|..$|}, *{", "\n", x$Geom, perl=T), sep=","))))
names(bar) <- sub("^V(\\d+)", "Geom\\1", names(bar))