2016-12-04 2 views
1

Я нахожу некоторые субоптимальные шаги в моем текущем рабочем процессе анализа данных, когда дело доходит до переключения между длинными и широкими форматами. Рассмотрим три следы показано ниже, с общими x значениями,long vs wide, tidy vs эффективный

enter image description here

Мои данные в длинном формате, полезно для построения и всех видов зычный вещей, но для некоторых частей анализа, кажется, гораздо проще иметь дело с широким (матричным) форматом. Например, в этом фиктивном примере я могу установить базовую линию на 0 для всех трасс, вычитая среднее значение для каждой трассы между 0 и 0,25 (заштрихованная серая область).

Я не могу найти простой способ делать подобные вещи в длинном формате.

Моя текущая стратегия - вернуться к широкому формату, но i) Я никогда не помню правильный синтаксис для dcast/reshape, ii) это довольно неэффективно, чтобы продолжать движение вперед и назад между ними.

dwide <- reshape2::dcast(dlong, x~..., value.var="y") 
dwide[,-1] <- sweep(dwide[,-1], 2, colMeans(dwide[dwide$x < 0.25, -1]), FUN="-") 
dlong2 <- melt(dwide, id="x") 

enter image description here

я пропустил некоторые инструменты, которые могли бы помочь? Я открыт для предложений data.table.


Полный воспроизводимый пример:

library(ggplot2) 
library(plyr) 
library(reshape2) 

## dummy data as noisy lorentzian-shaped peaks with random offset 

set.seed(1234) 
fake_data <- function(a, x = seq(0, 1, length=100)){ 
    data.frame(x = x, 
      y = jitter(1e-3/((x - a)^2 + 1e-3) + runif(1,0,1), 
        amount = 0.1)) 
} 

## apply function to all combinations of parameters (one here) 
dlong <- plyr::mdply(data.frame(a = c(0.4,0.5,0.6)), fake_data) 

ggplot(dlong, aes(x, y, colour=factor(a))) + geom_line() + 
    annotate("rect", xmin=-Inf, xmax=0.25, ymin=-Inf, ymax=Inf, fill="grey", alpha = 0.3) + 
    theme_minimal() 

dwide <- reshape2::dcast(dlong, x~..., value.var="y") 
str(dwide) 

dwide[,-1] <- sweep(dwide[,-1], 2, colMeans(dwide[dwide$x < 0.25, -1]), FUN="-") 
dlong2 <- melt(dwide, id="x") 

ggplot(dlong2, aes(x, value, colour=variable)) + geom_line() + 
    theme_minimal() 
+1

Я считаю, '' tidyr' в gather' и 'spread' требуют меньше, чем мысль' reshape2', за исключением того, что 'spread' может быть очень тонким в отношении индексов.Здесь 'dwide <- dlong %>% spread (a, y)' и 'dlong2 <- dwide %>% gather (variable, value, -x)' (или используйте 'a' и' y' вместо 'variable' и' value', чтобы сохранить оригинал имена). – alistaire

+0

Согласен, они кажутся более интуитивными. Я попытаюсь использовать их больше – baptiste

ответ

6

Может быть, ваш минимальный пример слишком тривиальный, чтобы охватить все случаи, когда вы могли бы хотеть идти долго широкий долго. Но для примера, по крайней мере, я обычно использую data.table для такого рода работы:

setDT(dlong)[, y2 := y - mean(y[x < 0.25]), by=a] 

ggplot(dlong, aes(x, y2, colour=factor(a))) + 
    geom_line() + 
    theme_minimal() 

enter image description here

Рассекая это вниз:

  • by = a группы данных, так что операция во втором аргументе [ .data.table применяется к подмножествам dlong, соответствующим каждому значению a

  • y2 := y - mean(y[x < 0.25]) поэтому вычисляется для каждого значения а, отдельно

  • := является специальным оператор в data.table, который обеспечивает назначение в качестве ссылки, а не присваивание путем копирования (его очень эффективный)

  • 1-ый аргумента [. datat.table оставлено здесь пустым, потому что мы хотим работать со всеми строками исходных данных dlong.

Практически то же самое можно сделать с помощью dplyr

dlong %>% 
    group_by(a) %>% 
    mutate(y2 = y - mean(y[x < 0.25])) 
+0

спасибо, это звучит многообещающе. Я не использую data.table, поэтому синтаксис для меня немного незнакомый. Вы правы в том, что пример, возможно, слишком минимален ... Я посмотрю, могу ли я представить что-то более убедительное. – baptiste

+3

В dplyr: 'dlong%>% group_by (a)%>% mutate (y2 = y - mean (y [x < 0.25])) %>% ggplot (aes (x, y2, color = factor (a))) + geom_line() + theme_minimal() ' – alistaire