【问题标题】:Monthly time trend from dataframe of dates来自日期数据框的每月时间趋势
【发布时间】:2019-04-25 12:15:15
【问题描述】:

我有一个如下所示的数据集:

  group id      date1      date2      date3      date4
1     1  1 1991-10-14 1992-05-20 1992-12-09 1993-06-30
2     1  2       <NA> 1992-05-21 1992-12-10 1993-06-29
3     1  3       <NA>       <NA> 1992-12-08 1993-06-29
4     1  4 1991-10-14 1992-05-19       <NA>       <NA>
5     1  5 1991-10-15 1992-05-21       <NA> 1993-06-30
6     1  6 1991-10-15       <NA>       <NA> 1993-06-30

这里的数据是R格式的:

structure(list(group = c(1L, 1L, 1L, 1L, 1L, 1L), 
               id = 1:6, 
               date1 = structure(c(7956, NA, NA, 7956, 7957, 7957), class = "Date"), 
               date2 = structure(c(8175, 8176, NA, 8174, 8176, NA), class = "Date"), 
               date3 = structure(c(8378, 8379, 8377, NA, NA, NA), class = "Date"), 
               date4 = structure(c(8581, 8580, 8580, NA, 8581, 8581), class = "Date")), 
          .Names = c("group", "id", "date1", "date2", "date3", "date4"),
          row.names = c(NA, 6L), class = "data.frame")

也就是说,我们有一个分组变量、几个人和四个可能的兴趣日期。

现在我想以此为每个人构建一个线性月时间趋势。换句话说,我尝试在第一个非NA 日期构建一个值为 1 的趋势。之后,其余非NA 期间的趋势是自第一个非NA 日期以来经过的月份。

我的目标是这个结构(个人 1,组 1):

  group id period trend
1     1  1      1     1
2     1  1      2     8
3     1  1      3    15
4     1  1      4    21

也就是说,自 t = 1 以来经过几个月的熔融 data.frame。

我玩过这个帖子的想法:Number of months between two dates。但是,我找不到不涉及for-loop 和大量if-statements 的解决方案。

任何帮助表示赞赏!

【问题讨论】:

  • 请将数据框的定义包含在问题本身中。
  • 我将它包含在问题的底部。

标签: r date dataframe trend


【解决方案1】:

这是使用dplyrtidyr 的一种潜在解决方案:

library(dplyr)
library(tidyr)
library(stringr)

df %>%
  gather(period, date, -group, -id) %>%
  arrange(group, id, period) %>%
  mutate(date = as.Date(date)) %>%
  group_by(group, id) %>%
  filter(!all(is.na(date))) %>% 
  mutate(
    trend = as.integer(
      floor(difftime(date, date[which.max(!is.na(date))], units = 'days') / 30)
      ) + 1,
    period = str_replace(period, 'date', '')
    ) %>%
  select(-date)

输出如下:

# A tibble: 24 x 4
# Groups:   group, id [6]
   group    id period trend
   <int> <int>  <chr> <dbl>
 1     1     1      1     1
 2     1     1      2     8
 3     1     1      3    15
 4     1     1      4    21
 5     1     2      1    NA
 6     1     2      2     1
 7     1     2      3     7
 8     1     2      4    14
 9     1     3      1    NA
10     1     3      2    NA
# ... with 14 more rows

注意:已编辑以添加过滤器以过滤掉给定组/ID 的所有日期均为 NA 的情况。否则,which,max 将失败。

【讨论】:

  • 只是一个注释以供将来参考:对于这个解决方案,至少我需要library(stringr) for str_replace()
  • 是的。已编辑。抱歉,我错过了。
【解决方案2】:

data.table 方法

我将四舍五入和/或为您添加 +1.. 这在几个月内总是很棘手。我个人尽量避免这种情况,并计算几天或几周(或几乎任何时间,但几个月)......

library( data.table)
dt <- melt ( as.data.table( df ), id.vars = c("group", "id"), variable.name = "date_id", value.name = "date" )
setkey(dt, id, group, date_id)
dt[, diff := lubridate::interval(  date[which.min( date ) ], date ) / months(1) , by = c("group", "id")]

head(dt)
#    group id date_id       date      diff
# 1:     1  1   date1 1991-10-14  0.000000
# 2:     1  1   date2 1992-05-20  7.193548
# 3:     1  1   date3 1992-12-09 13.833333
# 4:     1  1   date4 1993-06-30 20.533333
# 5:     1  2   date1       <NA>        NA
# 6:     1  2   date2 1992-05-21  0.000000

【讨论】:

    猜你喜欢
    • 2022-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 2012-05-12
    • 2015-07-09
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    相关资源
    最近更新 更多