Объединить элементы списка в соответствии с общим значением фрейма данных

Продолжение этого вопроса здесь, хотя пример конкретный, это похоже на обобщаемое приложение, поэтому я думаю, что стоит отдельная тема:

Общий вопрос: как мне взять элементы в списке, которые соответствуют значению в исходном фрейме данных, и объединить их в соответствии с этим значением в исходном фрейме данных, особенно если элементы списка имеют разную длину?

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

Вот некоторые фактические данные:

structure(list(date = structure(c(15706, 15707, 15708, 15709, 
15710, 15706, 15707, 15708), class = "Date"), segment = structure(c(1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L), .Label = c("abc", "xyz"), class = "factor"), 
    a = c(76L, 92L, 96L, 76L, 80L, 91L, 54L, 62L), x = c(964L, 
    505L, 968L, 564L, 725L, 929L, 748L, 932L), k = c(27L, 47L, 
    36L, 40L, 33L, 46L, 30L, 36L), value = c(6872L, 5993L, 5498L, 
    5287L, 6835L, 6622L, 5736L, 7218L)), .Names = c("date", "segment", 
"a", "x", "k", "value"), row.names = c(NA, -8L), class = "data.frame")

Так что для сегмента "abc" Я ПРОСТО забочусь о (value/a) относительно его эталона 75. а для сегмента "xyz" Я ПРОСТО забочусь о (k/x) относительно его эталона 0.04.

В конечном итоге я хочу, чтобы данные выглядели так:

        date   abc   xyz
1 2013-01-01  0.21  0.24
2 2013-01-02 -0.13  0.00
3 2013-01-03 -0.24 -0.03
4 2013-01-04 -0.07  0.00
5 2013-01-05  0.14  0.00

Где, поскольку "xyz" имел информацию только за 2013-01-01 - 2013-01-03, он получает 0 для всех после.

Как я дошел до этого пункта было:

определить аргументы для передачи в mapply

splits <- split(test, test$segment)
metrics <- c("ametric","xmetric")
benchmarks <- c(75,0.04)

и функция, чтобы получить производительность по сравнению с эталоном

performance <- function(splits,metrics,benchmarks){
    (splits[,metrics]/benchmarks)-1
}

Передайте это mapply:

temp <- mapply(performance, splits, metrics, benchmarks)

Проблема в том, что, поскольку разбиения были разной длины, выходные данные выглядят так:

summary(temp)

    Length Class  Mode   
abc 5      -none- numeric
xyz 3      -none- numeric

Есть ли способ ввести даты из исходного фрейма данных для каждого разделения и объединить в соответствии с этими датами (с 0, где нет данных)?

1 ответ

Вам просто нужно установить SIMPLIFY=FALSE аргумент mapplyтогда вы можете использовать do.call с rbind поместить все обратно в один фрейм данных:

> temp <- mapply(performance, splits, metrics, benchmarks)
> do.call('rbind',mapply(cbind, splits, performance=temp, SIMPLIFY=FALSE))
            date segment  a   x  k value  performance
abc.1 2013-01-01     abc 76 964 27  6872 1.333333e-02
abc.2 2013-01-02     abc 92 505 47  5993 2.266667e-01
abc.3 2013-01-03     abc 96 968 36  5498 2.800000e-01
abc.4 2013-01-04     abc 76 564 40  5287 1.333333e-02
abc.5 2013-01-05     abc 80 725 33  6835 6.666667e-02
xyz.6 2013-01-01     xyz 91 929 46  6622 2.322400e+04
xyz.7 2013-01-02     xyz 54 748 30  5736 1.869900e+04
xyz.8 2013-01-03     xyz 62 932 36  7218 2.329900e+04
Другие вопросы по тегам