一段时间以前,在 plyr
邮件列表上出现了这个问题(由@kohske提出),Peter Meilstrup 提供了一个解决方案,适用于特定情况:
keeping.order <- function(data, fn, ...) {
col <- ".sortColumn"
data[,col] <- 1:nrow(data)
out <- fn(data, ...)
if (!col %in% colnames(out)) stop("Ordering column not preserved by function")
out <- out[order(out[,col]),]
out[,col] <- NULL
out
}
d <- structure(list(g = c(2L, 2L, 1L, 1L, 2L, 2L), v = c(-1.90127112738315,
-1.20862680183042, -1.13913266070505, 0.14899803094742, -0.69427656843677,
0.872558638137971)), .Names = c("g", "v"), row.names = c(NA,
-6L), class = "data.frame")
ddply(d, .(g), mutate, v=scale(v))
keeping.order(d, ddply, .(g), mutate, v=scale(v))
请阅读
这篇文章,了解Hadley关于为什么这个功能可能不够通用以将其纳入
ddply
的注释,特别是在您的情况下,每个部分返回的行数可能较少。如果
ddply
输出的内容排序方式不符合您的要求,您基本上有两个选择:预先使用有序因子指定拆分变量的所需排序顺序,或在事后手动对输出进行排序。例如,考虑以下数据:
d <- data.frame(x1 = rep(letters[1:3],each = 5),
x2 = rep(letters[4:6],5),
x3 = 1:15,stringsAsFactors = FALSE)
目前使用字符串。 ddply
将对输出进行排序,在这种情况下,将采用默认的词法顺序:
> ddply(d,.(x1,x2),summarise, val = sum(x3))
x1 x2 val
1 a d 5
2 a e 7
3 a f 3
4 b d 17
5 b e 8
6 b f 15
7 c d 13
8 c e 25
9 c f 27
> ddply(d[sample(1:15,15),],.(x1,x2),summarise, val = sum(x3))
x1 x2 val
1 a d 5
2 a e 7
3 a f 3
4 b d 17
5 b e 8
6 b f 15
7 c d 13
8 c e 25
9 c f 27
如果最终的数据框不是按照“正确”的顺序排列,那很可能是因为你希望其中一些变量成为有序因子。假设我们真的希望将 x1
和 x2
排序如下:
d$x1 <- factor(d$x1, levels = c('b','a','c'),ordered = TRUE)
d$x2 <- factor(d$x2, levels = c('d','f','e'), ordered = TRUE)
现在当我们使用
ddply
时,结果的排序将如我们所愿:
> ddply(d,.(x1,x2),summarise, val = sum(x3))
x1 x2 val
1 b d 17
2 b f 15
3 b e 8
4 a d 5
5 a f 3
6 a e 7
7 c d 13
8 c f 27
9 c e 25
这个故事的道理是,如果
ddply
输出的顺序不是你想要的,那么你应该使用有序因子来拆分变量。
write.table
没有任何关系;标题应该更改。 - Brian Diggs