我现在有以下格式的键值数据
column1 column2 column3
length:30 width:20
length:20 height:10 width:10
现在我想将其转换为以下格式的数据框
Length width height
32 20
40 30 10
提前致谢
答案 0 :(得分:1)
您可以使用sub
setNames(data.frame(lapply(dat, function(x) sub("[a-z]+:", "", x))),
c("length", "width"))
# length width
# 1 32 20
# 2 40 30
有关更新的问题,
dat <- unlist(dat, use.names = F) # convert to list
keys <- unique(sub("([a-z]):.*", "\\1", dat)) # extract the keys
keys <- keys[keys!=""] # remove empty strings like in your example
## Key-values in list
keyvals <- setNames(lapply(keys, function(x) {
as.numeric(sub("\\D+", "", grep(x, dat, fixed=T, value=T)))
}), keys)
## Convert to data.frame
as.data.frame(do.call(cbind, lapply(keyvals, `length<-`, max(lengths(keyvals)))))
# length width height
# 1 30 20 10
# 2 20 10 NA
答案 1 :(得分:0)
使用dplyr/tidyr
的选项。我们使用gather
将'wide'格式转换为'long',使用''
删除空行(filter
),使用separate
创建两个变量('Val1'和'Val2')通过在:
分隔符处分隔字符串,删除不需要的列(select(-Var)
),按其中一个变量('Val1')分组,创建一个序列列('indx'),并从'long'格式转换回'wide'格式(spread
)。
library(dplyr)
library(tidyr)
gather(df1, Var, Val) %>%
filter(Val!='') %>%
separate(Val, c('Val1', 'Val2'), convert=TRUE) %>%
select(-Var) %>%
group_by(Val1) %>%
mutate(indx=row_number()) %>%
spread(Val1, Val2) %>%
select(-indx)
# height length width
#1 10 30 20
#2 NA 20 10
使用data.table
的类似方法。我们unlist
初始数据集,并使用单个列(setDT
)将其转换为“data.table”。使用deve版本的'data.table'中的tstrsplit
,即v1.9.5
,我们会在:
分割。根据分组变量'V1'创建序列列('indx'),删除'NA'行并使用dcast
中的data.table
将'long'转换回'wide'格式
library(data.table)#v1.9.5+
DT <- setDT(list(unlist(df1)))[, tstrsplit(V1, ':', type.convert=TRUE)
][, ind:=1:.N, V1][!is.na(V1)]
dcast(DT, ind~V1, value.var='V2')
# ind height length width
#1: 1 10 30 20
#2: 2 NA 20 10
df1 <- structure(list(column1 = c("length:30", "length:20"),
column2 = c("width:20",
"height:10"), column3 = c("", "width:10")), .Names = c("column1",
"column2", "column3"), class = "data.frame", row.names = c(NA, -2L))