use*_*830 5 r duplicates plyr reshape
我有一个很大的data.frame(20000多个条目),格式如下:
id D1 D2
1 0.40 0.21
1 0.00 0.00
1 0.53 0.20
2 0.17 0.17
2 0.25 0.25
2 0.55 0.43
Run Code Online (Sandbox Code Playgroud)
每个ID可以重复3-20次。我想将重复的行合并到新列中,所以新的data.frame看起来像:
id D1 D2 D3 D4 D5 D6
1 0.40 0.21 0.00 0.00 0.53 0.20
2 0.17 0.17 0.25 0.25 0.55 0.43
Run Code Online (Sandbox Code Playgroud)
我之前使用plyr操纵过data.frames,但不确定如何解决此问题。任何帮助将不胜感激。
最好的办法是只使用melt并dcast从“reshape2”。但是在转到该选项之前,让我们看看我们还有什么可用的东西:
您提到每个“ id”的行数不平衡。这将使放入一个整齐的矩形有些困难data.frame。
这里有一些例子。
mydf <- structure(list(id = c(1, 1, 1, 2, 2, 2),
D1 = c(0.4, 0, 0.53, 0.17, 0.25, 0.55),
D2 = c(0.21, 0, 0.2, 0.17, 0.25, 0.43)),
.Names = c("id", "D1", "D2"), row.names = c(NA, 6L),
class = "data.frame")
mydf
# id D1 D2
# 1 1 0.40 0.21
# 2 1 0.00 0.00
# 3 1 0.53 0.20
# 4 2 0.17 0.17
# 5 2 0.25 0.25
# 6 2 0.55 0.43
Run Code Online (Sandbox Code Playgroud)
有了这些数据,您可以使用aggregate:
do.call(data.frame, aggregate(. ~ id, mydf, as.vector))
# id D1.1 D1.2 D1.3 D2.1 D2.2 D2.3
# 1 1 0.40 0.00 0.53 0.21 0.00 0.20
# 2 2 0.17 0.25 0.55 0.17 0.25 0.43
Run Code Online (Sandbox Code Playgroud)
如果您为“ id = 2”添加了第四个值,aggregate则无法在此处使用:
mydf[7, ] <- c(2, .44, .33)
do.call(data.frame, aggregate(. ~ id, mydf, as.vector))
# Error in data.frame(`0` = c(0.4, 0, 0.53), `1` = c(0.17, 0.25, 0.55, 0.44 :
# arguments imply differing number of rows: 3, 4
Run Code Online (Sandbox Code Playgroud)
最好只包含一个list结果vectors:
lapply(split(mydf[-1], mydf[[1]]), function(x) unlist(x, use.names=FALSE))
# $`1`
# [1] 0.40 0.00 0.53 0.21 0.00 0.20
#
# $`2`
# [1] 0.17 0.25 0.55 0.44 0.17 0.25 0.43 0.33
#
Run Code Online (Sandbox Code Playgroud)
或者,如果您坚持使用矩形data.frame,请探索几种工具来处理rbind不平衡的数据之一,例如,rbind.fill来自“ plyr”的数据:
library(plyr)
rbind.fill(lapply(split(mydf[-1], mydf[[1]]),
function(x) data.frame(t(unlist(x, use.names=FALSE)))))
# X1 X2 X3 X4 X5 X6 X7 X8
# 1 0.40 0.00 0.53 0.21 0.00 0.20 NA NA
# 2 0.17 0.25 0.55 0.44 0.17 0.25 0.43 0.33
Run Code Online (Sandbox Code Playgroud)
或者,您可以按以下方式使用meltand dcastfrom“ reshape2”:
library(reshape2)
x <- melt(mydf, id.vars = "id")
## ^^ That's not enough information for `dcast`
## We need a "time" variable too, so use `ave`
## to create one according to the number of
## values per ID.
x$time <- ave(x$id, x$id, FUN = seq_along)
## ^^ I would probably actually stop at this point.
## Long data with proper ID and "time" values
## tend to be easier to work with and many
## other functions in R work more nicely with
## this long data format.
dcast(x, id ~ time, value.var = "value")
# id 1 2 3 4 5 6 7 8
# 1 1 0.40 0.00 0.53 0.21 0.00 0.20 NA NA
# 2 2 0.17 0.25 0.55 0.44 0.17 0.25 0.43 0.33
Run Code Online (Sandbox Code Playgroud)