所以我有data.frame
dat = data.frame(x = c('Sir Lancelot the Brave', 'King Arthur',
'The Black Knight', 'The Rabbit'), stringsAsFactors=F)
> dat
x
1 Sir Lancelot the Brave
2 King Arthur
3 The Black Knight
4 The Rabbit
我想将其转换为数据框
> dat2
x 1 2 3 4
1 Sir Lancelot the Brave Sir Lancelot the Brave
2 King Arthur King Arthur
3 The Black Knight The Black Knight
4 The Rabbit The Rabbit
strsplit将数据作为列表返回
sbt <- strsplit(dat$x, " ")
> sbt
[[1]]
[1] "Sir" "Lancelot" "the" "Brave"
[[2]]
[1] "King" "Arthur"
[[3]]
[1] "The" "Black" "Knight"
[[4]]
[1] "The" "Rabbit"
和as.data.table不会在应有的位置创建NULL值,但会重复值
> t(as.data.table(sbt))
[,1] [,2] [,3] [,4]
V1 "Sir" "Lancelot" "the" "Brave"
V2 "King" "Arthur" "King" "Arthur"
V3 "The" "Black" "Knight" "The"
V4 "The" "Rabbit" "The" "Rabbit"
我想我真的想要as.data.table(x,repeat = FALSE)的参数,否则我怎么能完成这份工作呢?
答案 0 :(得分:11)
这是一个老问题,我知道,但我想我会分享另外两个选项。
concat.split
完全是针对这类事情而设计的。
library(splitstackshape)
concat.split(dat, "x", " ")
# x x_1 x_2 x_3 x_4
# 1 Sir Lancelot the Brave Sir Lancelot the Brave
# 2 King Arthur King Arthur
# 3 The Black Knight The Black Knight
# 4 The Rabbit The Rabbit
data.table
最近(截至1.8.11版本,我相信)对其武器库有一些补充,特别是在这种情况下dcast.data.table
。要使用它,unlist
拆分数据(就像在@mnel的回答中所做的那样),使用.N
创建一个“时间”变量(每行有多少新值),然后使用dcast.data.table
将数据转换为您正在寻找的形式。
library(data.table)
library(reshape2)
packageVersion("data.table")
# [1] ‘1.8.11’
DT <- data.table(dat)
S1 <- DT[, list(X = unlist(strsplit(x, " "))), by = seq_len(nrow(DT))]
S1[, Time := sequence(.N), by = seq_len]
dcast.data.table(S1, seq_len ~ Time, value.var="X")
# seq_len 1 2 3 4
# 1: 1 Sir Lancelot the Brave
# 2: 2 King Arthur NA NA
# 3: 3 The Black Knight NA
# 4: 4 The Rabbit NA NA
答案 1 :(得分:9)
这是一个选项。单一的复杂性是你需要先将每个向量转换为一行data.frame,因为data.frames是rbind.fill()
所期望的。
library(plyr)
rbind.fill(lapply(sbt, function(X) data.frame(t(X))))
# X1 X2 X3 X4
# 1 Sir Lancelot the Brave
# 2 King Arthur <NA> <NA>
# 3 The Black Knight <NA>
# 4 The Rabbit <NA> <NA>
但是,我自己的倾向是使用基数R,就像这样:
n <- max(sapply(sbt, length))
l <- lapply(sbt, function(X) c(X, rep(NA, n - length(X))))
data.frame(t(do.call(cbind, l)))
# X1 X2 X3 X4
# 1 Sir Lancelot the Brave
# 2 King Arthur <NA> <NA>
# 3 The Black Knight <NA>
# 4 The Rabbit <NA> <NA>
答案 2 :(得分:6)
sbt = strsplit(dat$x, " ")
sbt
#[[1]]
#[1] "Sir" "Lancelot" "the" "Brave"
#[[2]]
#[1] "King" "Arthur"
#[[3]]
#[1] "The" "Black" "Knight"
#[[4]]
#[1] "The" "Rabbit"
ncol = max(sapply(sbt,length))
ncol
# [1] 4
as.data.table(lapply(1:ncol,function(i)sapply(sbt,"[",i)))
# V1 V2 V3 V4
# 1: Sir Lancelot the Brave
# 2: King Arthur NA NA
# 3: The Black Knight NA
# 4: The Rabbit NA NA
答案 3 :(得分:2)
使用data.table
,因为它显示您正在尝试使用它。
library(data.table)
DT <- data.table(dat)
DTB <- DT[, list(y = unlist(strsplit(x, ' '))), by = x]
new <- rep(NA_character_, DTB[,.N,by =x][which.max(N), N])
names(new) <- paste0('V', seq_along(new))
DTB[,{.new <- new
.new[seq_len(.N)] <- y
as.list(.new)} ,by= x]
或使用reshape2
dcast
重塑
library(reshape2)
dcast(DTB[,list(id = seq_len(.N),y),by= x ], x ~id, value.var = 'y')
答案 4 :(得分:0)
这是一个使用tidyr
的简单方法。
library(tidyr)
ncol <- max(sapply(dat, length))
dat %>%
separate(x, paste0("V", seq(1,ncol)))
注意:您会收到警告,但是,它基本上告诉您separate
正在使用NA
填充数据。所以你可以忽略警告。