Интересно, есть ли способ применить функцию к каждой строке data.frame, чтобы классы столбцов сохранялись? Давайте посмотрим на пример, чтобы пояснить, что я имею в виду:Применить функцию к каждой строке data.frame и сохранить классы столбцов
test <- data.frame(startdate = as.Date(c("2010-03-07", "2013-09-13", "2011-11-12")),
enddate = as.Date(c("2010-03-23", "2013-12-01", "2012-01-05")),
nEvents = c(123, 456, 789))
Предположим, что я хотел бы расширить data.frame test
, вставляя все дни между startdate
и enddate
и распределить количество событий в течение этих дней. Моя первая попытка сделать это было так:
eventsPerDay1 <- function(row) {
n_days <- as.numeric(row$enddate - row$startdate) + 1
data.frame(date = seq(row$startdate, row$enddate, by = "1 day"),
nEvents = rmultinom(1, row$nEvents, rep(1/n_days, n_days)))
}
apply(test, 1, eventsPerDay1)
Это, однако, не представляется возможным, потому что apply
вызовы as.matrix
на test
и, таким образом, он преобразуется в матрицу символов и все классы столбцов будут потеряны.
Я уже нашел два обходных пути, которые вы можете найти ниже, так что мой вопрос более похож на философию.
library(magrittr)
############# Workaround 1
eventsPerDay2 <- function(startdate, enddate, nEvents) {
n_days <- as.numeric(enddate - startdate) + 1
data.frame(date = seq(startdate, enddate, by = "1 day"),
nEvents = rmultinom(1, nEvents, rep(1/n_days, n_days)))
}
mapply(eventsPerDay2, test$startdate, test$enddate, test$nEvents, SIMPLIFY = F) %>%
do.call(rbind, .)
############# Workaround 2
seq_along(test) %>%
lapply(function(i) test[i, ]) %>%
lapply(eventsPerDay1) %>%
do.call(rbind, .)
Моя «проблема» с обходные заключается в следующем:
- Обход 1: Это может быть не лучшая причина, но я просто не люблю
mapply
. Он имеет другую подпись, чем другие функции*apply
(поскольку порядок аргументов отличается), и я всегда чувствую, что циклfor
был бы более ясным. - Обход проблемы 2: будучи очень гибким, я думаю, что на первый взгляд не ясно, что происходит.
Так кто-нибудь знает функцию, чей вызов будет выглядеть как apply(test, 1, eventsPerDay1)
, и это сработает?
Если вы хотите сохранить класс, используйте 'lapply' цикл по последовательности строк, а не' apply' – akrun
@akrun спасибо за это предложение, но разве это не то, что я сделал в «обходном пути 2»? Если нет, уточните, что вы имеете в виду. Благодаря! – AEF
Да, вы правы в этом. Я опубликовал решение, используя 'data.table'. Пожалуйста, проверьте, не делает ли это лучше – akrun