将类似python的列表转换为R嵌套向量

时间:2016-04-20 15:15:48

标签: r dplyr tidyr

我正在尝试“自动”将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,所以它不解析它。

3 个答案:

答案 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))