我正在尝试转换格式数据:
dt <- data.table(foo = c(c('a=a1|b=b1'),c('a=a2|b=b2|c=c2'),c('a=a3|d=d3')))
形成:
data.table(a=c('a1','a2','a3'),b=c('b1','b2',NA),c=c(NA,'c2',NA),d=c(NA,NA,'d3'))
我尝试使用以下方法解析第一步:
lapply(dt$foo, function(x) unlist(strsplit(x, split = '|', fixed = T)))
但无法继续前进。有什么指针吗?
答案 0 :(得分:4)
如果提供更多案例,将会更新。这不是data.table
,因为我没有使用它,但是afaik应该仍然可以使用吗?也许如果先被强迫data.frame
。
library(tidyverse)
dt <- tibble(foo = c(c('a=a1|b=b1'),c('a=a2|b=b2|c=c2'),c('a=a3|d=d3')))
tibble(a=c('a1','a2','a3'),b=c('b1','b2',NA),c=c(NA,'c2',NA),d=c(NA,NA,'d3'))
#> # A tibble: 3 x 4
#> a b c d
#> <chr> <chr> <chr> <chr>
#> 1 a1 b1 <NA> <NA>
#> 2 a2 b2 c2 <NA>
#> 3 a3 <NA> <NA> d3
dt %>%
mutate(foo = str_split(foo, pattern = "\\|")) %>%
rowid_to_column() %>%
unnest() %>%
separate(foo, into = c("col", "val"), sep = "=") %>%
spread(col, val)
#> # A tibble: 3 x 5
#> rowid a b c d
#> <int> <chr> <chr> <chr> <chr>
#> 1 1 a1 b1 <NA> <NA>
#> 2 2 a2 b2 c2 <NA>
#> 3 3 a3 <NA> <NA> d3
由reprex package(v0.2.0)创建于2018-04-12。
答案 1 :(得分:3)
将我的评论转换为答案,您可以尝试:
library(splitstackshape)
cSplit(dt[, row := .I], "foo", "|", "long")[
, cSplit(.SD, "foo", "=")][
, dcast(.SD, row ~ foo_1, value.var = "foo_2")]
# row a b c d
# 1: 1 a1 b1 <NA> <NA>
# 2: 2 a2 b2 c2 <NA>
# 3: 3 a3 <NA> <NA> d3
您当然也可以只使用strsplit
,tstrsplit
和dcast
的组合。
dt[, unlist(strsplit(foo, "|", TRUE)), 1:nrow(dt)][
, c("col", "val") := tstrsplit(V1, "=", fixed = TRUE)][
, dcast(.SD, nrow ~ col, value.var = "val")]
# nrow a b c d
# 1: 1 a1 b1 <NA> <NA>
# 2: 2 a2 b2 c2 <NA>
# 3: 3 a3 <NA> <NA> d3
答案 2 :(得分:1)
一个选项是使用read.table
函数将值读取为key-value
对,然后最终转换为data.frame。 dplyr::bind_rows
可以帮助您加入不同的行。
dt <- data.table(foo = c(c('a=a1|b=b1'),c('a=a2|b=b2|c=c2'),c('a=a3|d=d3')))
library(dplyr)
bind_rows(mapply(function(x){
t <- read.table(text = gsub("\\|","\n",x), sep=c("="), stringsAsFactors=FALSE)
t <- as.data.frame(t(t), stringsAsFactors = FALSE)
colnames(t) <- t[1,]
t <- t[-1,]
}, dt$foo))
# a b c d
# 1 a1 b1 <NA> <NA>
# 2 a2 b2 c2 <NA>
# 3 a3 <NA> <NA> d3
@abhiieor建议的 更新: data.table
解决方案如下:
library(data.table)
rbindlist(mapply(function(x){
t <- read.table(text = gsub("\\|","\n",x), sep=c("="), stringsAsFactors=FALSE)
t <- as.data.frame(t(t), stringsAsFactors = FALSE)
colnames(t) <- t[1,]
t <- t[-1,]
}, dt$foo), use.names = T, fill = T)