Вот решение, которое использует только ядро R. Сначала мы показываем входные данные, чтобы все это было самодостаточным:
DF <- data.frame(ID = c(1, 1, 2, 2),
ATTRIBUTE = c("A", "B", "B", "B"),
START = c("01-01-2000", "05-11-2001", "01-02-2002", "01-06-2008"),
END = c("15-03-2010", "06-02-2002", "08-05-2008", "01-07-2008"))
Теперь, когда у нас есть входные данные, решение следующее: yr
определяется как функция, извлекающая год. Суть вычисления заключается в утверждении, следующем за определением yr
. Для каждой строки DF
анонимная функция создает фрейм данных, содержащий годы, охватывающие столбец 1, и ATTRIBUTE
и ID
в столбцах 2 и 3. Например, фрейм данных, соответствующий первой строке DF
, представляет собой 11-ю строку data.frame(YEAR = 2000:2010, ATTRIBUTE = 1, ID = "A")
, а Кадр данных, соответствующий второй строке DF
, представляет собой две строки data.frame(YEAR = 2001:2002, ATTRIBUTE = 1, ID = "B")
. lapply
создает список таких фреймов данных, по одному для каждой строки DF
, поэтому в приведенном выше примере ввода он создает список с 4 компонентами. Используя do.call
, мы rbind
компоненты этого списка, т. е. отдельные фреймы данных, создаем один большой фрейм данных. Мы удаляем повторяющиеся строки (используя unique
) из этого большого фрейма данных, удаляем столбец ID
(третий столбец) и запускаем table
для результата:
yr <- function(d) as.numeric(sub(".*-", "", d))
out <- table(unique(do.call(rbind, lapply(1:nrow(DF), function(r) with(DF[r, ],
data.frame(YEAR = seq(yr(START), yr(END)), ATTRIBUTE, ID)))))[, -3])
Результирующая таблица:
> out
ATTRIBUTE
YEAR A B
2000 1 0
2001 1 1
2002 1 2
2003 1 1
2004 1 1
2005 1 1
2006 1 1
2007 1 1
2008 1 1
2009 1 0
2010 1 0
РЕДАКТИРОВАТЬ:
Позже Плакат указал, что память может быть проблемой, поэтому вот решение sqldf, которое обрабатывает ключевые большие промежуточные результаты в sqlite вне R (dbname = tempfile()
говорит ему сделать это), поэтому любое ограничение памяти R не повлияет на это. Он использует тот же ввод и ту же функцию yr
, показанную выше, и возвращает тот же результат, tab
такой же, как out
выше. Также попробуйте без dbname = tempfile()
, если он действительно помещается в памяти.
library(sqldf)
DF2 <- transform(DF, START = yr(START), END = yr(END))
years <- data.frame(year = min(DF2$START):max(DF2$END))
tab.df <- sqldf("select year, ATTRIBUTE, count(*) as count from
(select distinct year, ATTRIBUTE, ID
from years, DF2
where year between START and END)
group by year, ATTRIBUTE", dbname = tempfile())
tab <- xtabs(count ~., tab.df)
person
G. Grothendieck
schedule
24.10.2011
A
иB
) в год междуSTART
иEND
? - person daroczig   schedule 24.10.2011