Разверните строки по дате с использованием даты начала и окончания
Рассмотрим кадр данных формы
idnum start end 1993.1 17 1993-01-01 1993-12-31 1993.2 17 1993-01-01 1993-12-31 1993.3 17 1993-01-01 1993-12-31
с start
и end
типа Date
$ idnum : int 17 17 17 17 27 27 $ start : Date, format: "1993-01-01" "1993-01-01" "1993-01-01" "1993-01-01" ... $ end : Date, format: "1993-12-31" "1993-12-31" "1993-12-31" "1993-12-31" ...
Я хотел бы создать новый dataframe, который вместо этого ежемесячно наблюдает за каждой строкой, за каждый месяц между start
и end
(включая границы):
- Напишите много файлов в цикле for
- Добавить столбец «ранг» в кадр данных
- Как вы кодируете функцию R так, чтобы она «знала», чтобы искать «данные» для переменных в других аргументах?
- Матрица корреляции сюжетов в граф
- Перемещение столбцов в data.frame () без повторного набора
Желаемый результат
idnum month 17 1993-01-01 17 1993-02-01 17 1993-03-01 ... 17 1993-11-01 17 1993-12-01
Я не уверен, какой формат month
должен иметь, я в какой-то момент хочу группировать по idnum
, month
для регрессий в остальной части набора данных.
До сих пор для каждой отдельной строки seq(from=test[1,'start'], to=test[1, 'end'], by='1 month')
дает мне правильную последовательность – но как только я попробуйте применить это ко всему кадру данных, это не сработает:
> foo <- apply(test, 1, function(x) seq(x['start'], to=x['end'], by='1 month')) Error in to - from : non-numeric argument to binary operator
- найти все функции (включая частные) в пакете
- Есть ли такой «colsd» в R?
- Увеличение на 1 для каждого изменения в столбце
- Возвращаемый индекс наименьшего значения в векторе?
- Явное вызов return в функции или нет
- Добавление текста в таблицу grid.table
- вытащить p-значения и r-квадрат из линейной регрессии
- Найти ближайшее значение в векторе с бинарным поиском
Использование data.table
:
require(data.table) ## 1.9.2+ setDT(df)[ , list(idnum = idnum, month = seq(start, end, by = "month")), by = 1:nrow(df)] # you may use dot notation as a shorthand alias of list in j: setDT(df)[ , .(idnum = idnum, month = seq(start, end, by = "month")), by = 1:nrow(df)]
setDT
преобразует df
в data.table
. Затем для каждой строки, by = 1:nrow(df)
, мы создаем idnum
и month
мере необходимости.
Использование dplyr
:
test %>% group_by(idnum) %>% summarize(start=min(start),end=max(end)) %>% do(data.frame(idnum=.$idnum, month=seq(.$start,.$end,by="1 month")))
Обратите внимание, что здесь я не создаю последовательность между start
и end
для каждой строки, вместо этого это последовательность между min(start)
и max(end)
для каждого idnum
. Если вы хотите первый:
test %>% rowwise() %>% do(data.frame(idnum=.$idnum, month=seq(.$start,.$end,by="1 month")))
tidyverse
ответ
Данные
df <- structure(list(idnum = c(17L, 17L, 17L), start = structure(c(8401, 8401, 8401), class = "Date"), end = structure(c(8765, 8765, 8765 ), class = "Date")), class = "data.frame", .Names = c("idnum", "start", "end"), row.names = c(NA, -3L))
Ответ и вывод
library(tidyverse) df %>% nest(start, end) %>% mutate(data = map(data, ~seq(unique(.x$start), unique(.x$end), 1))) %>% unnest(data) # # A tibble: 365 x 2 # idnum data # # 1 17 1993-01-01 # 2 17 1993-01-02 # 3 17 1993-01-03 # 4 17 1993-01-04 # 5 17 1993-01-05 # 6 17 1993-01-06 # 7 17 1993-01-07 # 8 17 1993-01-08 # 9 17 1993-01-09 # 10 17 1993-01-10 # # ... with 355 more rows
Может быть, вы можете попробовать:
обновленный
Основано на комментариях @Ananda Mahto
res1 <- melt(setNames(lapply(1:nrow(test), function(x) seq(test[x, "start"], test[x, "end"], by = "1 month")), test$idnum))
Также,
res2 <- setNames(do.call(`rbind`, with(test, Map(`expand.grid`,idnum, Map(`seq`, start, end, by='1 month')))), c("idnum", "month")) head(res1) # idnum month #1 17 1993-01-01 #2 17 1993-02-01 #3 17 1993-03-01 #4 17 1993-04-01 #5 17 1993-05-01 #6 17 1993-06-01