Подтвердить что ты не робот

Использование dplyr для подсчета частоты взаимодействий должно включать нулевые отсчеты

Мой вопрос заключается в написании кода с помощью пакета dplyr в R

У меня относительно большой размер данных (около 5 миллионов строк) с двумя столбцами: первый с отдельным идентификатором (id), а второй с датой (date). В настоящее время каждая строка указывает на возникновение действия (взятого индивидуумом в столбце id) в дату в столбце даты. Есть около 300 000 уникальных людей и около 2600 уникальных дат. Например, начало данных выглядит следующим образом:

    id         date
    John12     2006-08-03
    Tom2993    2008-10-11
    Lisa825    2009-07-03
    Tom2993    2008-06-12
    Andrew13   2007-09-11

Я хотел бы изменить данные, чтобы у меня была строка для каждой возможной пары id x date, с дополнительным столбцом, который подсчитывает общее количество событий (возможно, принимая значение 0) для указанное лицо на данную дату.

У меня был некоторый успех с пакетом dplyr, который я использовал для подсчета количества дат даты id x, которые наблюдаются в данных.

Здесь код, который я использовал для табуляции id x date, подсчитывается до сих пор: (моя датафрейма называется df)

reduced = df %.% 
  group_by(id, date) %.%
  summarize(length(date))

Моя проблема в том, что (как я сказал выше) я бы хотел иметь набор данных, который также включает 0s для пар id x date, которые не имеют связанных действий. Например, если не было обнаруженного действия для John12 в 2007-10-10, я бы хотел, чтобы результат возвращал строку для этой пары id x date с числом 0.

Я подумал о создании фрейма выше, а затем слияния с пустым фреймом, но я убежден, что должно быть более простое решение. Любые предложения очень ценятся!

4b9b3361

Ответ 1

Вот простой вариант, вместо data.table:

library(data.table)

dt = as.data.table(your_df)

setkey(dt, id, date)

# in versions 1.9.3+
dt[CJ(unique(id), unique(date)), .N, by = .EACHI]
#          id       date N
# 1: Andrew13 2006-08-03 0
# 2: Andrew13 2007-09-11 1
# 3: Andrew13 2008-06-12 0
# 4: Andrew13 2008-10-11 0
# 5: Andrew13 2009-07-03 0
# 6:   John12 2006-08-03 1
# 7:   John12 2007-09-11 0
# 8:   John12 2008-06-12 0
# 9:   John12 2008-10-11 0
#10:   John12 2009-07-03 0
#11:  Lisa825 2006-08-03 0
#12:  Lisa825 2007-09-11 0
#13:  Lisa825 2008-06-12 0
#14:  Lisa825 2008-10-11 0
#15:  Lisa825 2009-07-03 1
#16:  Tom2993 2006-08-03 0
#17:  Tom2993 2007-09-11 0
#18:  Tom2993 2008-06-12 1
#19:  Tom2993 2008-10-11 1
#20:  Tom2993 2009-07-03 0

В версиях 1.9.2 или до того, как эквивалентное выражение опустит явный by:

dt[CJ(unique(id), unique(date)), .N]

Идея состоит в том, чтобы создать все возможные пары id и date (это то, что делает часть CJ), а затем объединить ее, подсчитывая вхождения.

Ответ 2

Вот как вы могли это сделать, хотя я использую dplyr только частично для вычисления частот в исходном df и для left_join. Как вы уже сказали в своем вопросе, я создал новый data.frame и объединил его с существующим. Я думаю, если вы хотите сделать это исключительно в dplyr, что потребует от вас как-то rbind много строк в этом процессе, и я предполагаю, что этот способ может быть быстрее, чем другой.

require(dplyr)

original <- read.table(header=T,text="    id         date
John12     2006-08-03
Tom2993    2008-10-11
Lisa825    2009-07-03
Tom2993    2008-06-12
Andrew13   2007-09-11", stringsAsFactors=F)

original$date <- as.Date(original$date) #convert to date

#get the frequency in original data in new column and summarize in a single row per group
original <- original %>%
  group_by(id, date) %>%
  summarize(count = n())            

#create a sequence of date as you need it
dates <- seq(as.Date("2006-01-01"), as.Date("2009-12-31"), 1)    

#create a new df with expand.grid to get all combinations of date/id
newdf <- expand.grid(id = original$id, date = dates)     

#remove dates
rm(dates)

#join original and newdf to have the frequency counts from original df
newdf <- left_join(newdf, original, by=c("id","date"))   

#replace all NA with 0 for rows which were not in original df
newdf$count[is.na(newdf$count)] <- 0