在安排的数据上使用mutate()中的滞后

时间:2019-03-02 04:54:51

标签: r date lag lubridate mutate

我正在处理类似于

的数据集
2019-03-02 15:43:41 WARN  HiveMetaStore:622 - Retrying creating default database after error: Error creating transactional connection factory
javax.jdo.JDOFatalInternalException: Error creating transactional connection factory
......
......
Exception in thread "main" org.apache.spark.sql.AnalysisException: java.lang.RuntimeException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient;
......
......
org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient;
Caused by: org.datanucleus.exceptions.NucleusException: Attempt to invoke the "HikariCP" plugin to create a ConnectionPool gave an error : The connection pool plugin of type "HikariCP" was not found in the CLASSPATH!

我有每个ID的第一个日期,我试图通过将days_prior添加到上一个日期来计算下一个日期。我正在使用lag函数来引用上一个日期。

data <-tribble(
  ~id, ~ dates, ~days_prior,
  1,20190101, NA,
  1,NA, 15,
  1,NA, 20,
  2, 20190103, NA,
  2,NA, 3,
  2,NA, 4)

这有效,但仅适用于下一行,因为您可以看到附加的数据。

enter image description here

我在做什么错?我希望所有日期都由mutate()计算。我应该采用哪种不同的方法进行计算。

2 个答案:

答案 0 :(得分:0)

我真的不知道lag在这里有什么帮助;除非我误解了,否则这里是使用tidyr::fill

的选项
data %>%
    group_by(id) %>%
    mutate(dates = as.Date(ymd(dates))) %>%
    fill(dates) %>%
    mutate(dates = dates + if_else(is.na(days_prior), 0L, as.integer(days_prior))) %>%
    ungroup()
## A tibble: 6 x 3
#     id dates      days_prior
#  <dbl> <date>          <dbl>
#1     1 2019-01-01         NA
#2     1 2019-01-16         15
#3     1 2019-01-21         20
#4     2 2019-01-03         NA
#5     2 2019-01-06          3
#6     2 2019-01-07          4

或稍作改动,将NA中的days_prior项替换为0

data %>%
    group_by(id) %>%
    mutate(
        dates = as.Date(ymd(dates)),
        days_prior = replace(days_prior, is.na(days_prior), 0)) %>%
    fill(dates) %>%
    mutate(dates = dates + as.integer(days_prior)) %>%
    ungroup()

更新

为回应您在评论中的澄清,这是您可以做的

data %>%
    group_by(id) %>%
    mutate(
        dates = as.Date(ymd(dates)),
        days_prior = replace(days_prior, is.na(days_prior), 0)) %>%
    fill(dates) %>%
    mutate(dates = dates + cumsum(days_prior)) %>%
    ungroup()
## A tibble: 6 x 3
#     id dates      days_prior
#  <dbl> <date>          <dbl>
#1     1 2019-01-01          0
#2     1 2019-01-16         15
#3     1 2019-02-05         20
#4     2 2019-01-03          0
#5     2 2019-01-06          3
#6     2 2019-01-10          4

答案 1 :(得分:0)

您可以使用na.locf包中的zoo来填写上一个观察日期,然后再添加前几天。

library("tidyverse")
library("zoo")
data %>%
  # Fill in NA dates with the previous non-NA date
  # The `locf` stands for "last observation carried forward"
  # Fill in NA days_prior with 0
  mutate(dates = zoo::na.locf(dates),
         days_prior = replace_na(days_prior, 0)) %>%
  mutate(dates = lubridate::ymd(dates) + days_prior)

此解决方案有两个假设:

  1. 行按id排序。您可以使用group_by(id)后跟ungroup()语句来解决这个假设,如Maurits Evers的解决方案所示。
  2. 对于每个ID,带有观察日期的行在组中排在第一位。在任何情况下,na.locffill都必须如此,因为这两个函数都使用先前的非NA条目来填充NA。

如果您不想对顺序进行任何假设,则可以使用data %>% arrange(id, dates)开头对行进行排序。