Как ddply () без сортировки? - PullRequest
       5

Как ddply () без сортировки?

8 голосов
/ 30 августа 2011

Я использую следующий код для суммирования своих данных, сгруппированных по составу, репликации и массе.

summaryDataFrame <- ddply(reviewDataFrame, .(Compound, Replicate, Mass), 
  .fun = calculate_T60_Over_T0_Ratio)

К сожалению, побочным эффектом является то, что результирующий кадр данных сортируется по этим полям. Я хотел бы сделать это и сохранить Compound, Replicate и Mass в том же порядке, что и в исходном фрейме данных. Есть идеи? Я попытался добавить столбец «Сортировка» последовательных целых чисел к исходным данным, но, конечно, я не могу включить это в .variables, так как я не хочу группировать по этому, и поэтому он не возвращается в summaryDataFrame.

Спасибо за помощь.

Ответы [ 2 ]

11 голосов
/ 30 августа 2011

Это появилось в списке рассылки 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 выводит что-то в порядке, который вы не намеревались, это хороший признак того, что вам следует использовать упорядоченные коэффициенты для переменных, на которые вы разбиваете.

1 голос
/ 30 августа 2011

В итоге я добавил столбец «индексации» к исходному фрейму данных. Он состоял из двух столбцов pasted с sep="_". Затем я создал еще один фрейм данных, состоящий только из unique членов столбца 'indexing' и счетчика 1:length(df). Я сделал ddply() на данных, которые вернули отсортированный фрейм данных. Затем, чтобы вернуть все в исходный порядок, я сделал merge() фрейм данных результатов и фрейм данных индекса (убедившись, что столбцы названы одинаково, это упрощается). Наконец я сделал order и удалил посторонние столбцы.

Не элегантное решение, но работающее.

Спасибо за помощь. Это заставило меня задуматься в правильном направлении.

...