Это появилось в списке рассылки plyr
некоторое время назад (поднято @kohske не меньше), и это решение, предлагаемое Питером Мейлструпом для ограниченных случаев:
#Peter's version used a function gensym to
# create the col name, but I couldn't track down
# what package it was in.
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
}
#Some sample data
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")
#This one resorts
ddply(d, .(g), mutate, v=scale(v)) #does not preserve order of d
#This one does not
keeping.order(d, ddply, .(g), mutate, v=scale(v)) #preserves order of d
Пожалуйста, прочитайте ветку для заметок Хэдли о том, почему эта функциональность может быть недостаточно общей, чтобы перейти в 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
выводит что-то в порядке, который вы не намеревались, это хороший признак того, что вам следует использовать упорядоченные коэффициенты для переменных, на которые вы разбиваете.