R - Интервалы даты и количества строк по дате - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть вопрос о более быстром способе вычисления чего-либо с интервалами дат

Мой ввод:

  • Фрейм данных: одна строка на пару (люди, период).В каждой строке у меня есть ID человека, дата начала и дата окончания.
  • Период времени: все даты день за днем ​​в течение двух лет

То, что я пытаюсь сделать, это рассчитать количество людей, у меня есть дата по дате.У меня есть код, который работает, но недостаточно эффективен с большим набором данных (~ от 100 тыс. До 1 млн строк).

В настоящее время проблема в том, что у меня два года, мой код 730 раз (365x2) выполняет следующие шаги:

  • Фильтрует набор данных по конкретной дате, включенной между началомдата и дата окончания
  • Рассчитать количество уникальных идентификаторов в отфильтрованном наборе данных. И эти операции очень длинные или невозможны для большого набора данных

Мне интересно, существует ли он лучшеи более быстрый способ сделать эти операции, как с агрегацией или с другой техникой.

Пример с коротким входом и выходом:

library(lubridate)
library(dplyr)

# Vector of date
vector_day <- seq(ymd('2017-01-01'), ymd('2018-12-30'), by= "days")

# Input Data
df <- data.frame(
      id_people = c(1, 2, 3, 4, 1),
      StartDate = c(as.Date("2018-11-01"), as.Date("2018-11-03"),as.Date("2018-12-01"),as.Date("2018-11-15") ,as.Date("2018-11-15")),
      EndDate = c(as.Date("2018-11-10"), as.Date("2018-12-04"),as.Date("2018-12-10"),as.Date("2018-11-17"), as.Date("2018-11-23")), 
      Gender = c("F", "F", "M", "F", "F"))


# Function to compute the number of people given a spécific date
compute_nb_f_by_day <- function(date) {

  cond1 <- df_f$StartDate <= date
  cond2 <- df_f$EndDate > date
  cond <- cond1 & cond2

  res <- length(unique(df_f[cond,]$id_people))
  return(res)

}

# An example of how the function works for on date
compute_nb_f_by_day(as.Date("2018-12-01"))

# Computation for all the dates
nb_f_by_day <- cbind(
               data.frame(vector_day),
               data.frame(nb_f_by_day <- sapply(vector_day, compute_nb_f_by_day)))

Спасибо.

1 Ответ

0 голосов
/ 17 декабря 2018

В данном примере это решение значительно быстрее, чем ваш код (ваш код: 0,132 с; этот код: 0,032 с в моей системе).Попробуйте проверить, значительно ли он улучшится для большого набора данных!

#-- Create the 'Interval'
df2 <- df %>%
  mutate(DateInterval = StartDate %--% EndDate)

#-- Create a result df instead of using cbind (more efficient)
result_df <- data.frame(Day = vector_day, Nb = NA)

#-- Get intervals that contain the days in vector_day
result_df$Nb <- sapply(vector_day, function(day) {sum(day %within% df2$DateInterval)})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...