【问题标题】:calculate time difference in weeks以周计算时差
【发布时间】:2021-12-06 08:35:08
【问题描述】:

我有一个这样的数据集

data <- data.table::data.table(id = seq(1:5),
                               t0_year = c(2000,2001,2002,2001,2000),
                               t0_week = c(4,32,44,15,11),
                               t1_date = as.Date(c("2010-07-31", "2010-12-31", "2010-02-08", "2005-07-05", "2000-07-20")))

我想计算 t1 和 t0 之间的周时差,但是对于 t0,我只有年份和周数,而对于 t1,我有确切的日期。

我用lubridate 尝试了不同的东西,但运气不佳。有人有解决办法吗?

【问题讨论】:

  • 一个无法计算日期之间的固定单位的差异,它们是不同的。最好的办法是确定一个范围,其中的差异可能是一个数字加或减 3.5,以表明您不知道哪个值是正确的。如果假设您的“周”从星期日或星期一或您选择的任何日期开始,那么...将t0 更改为Date(永久、作为新列或即时)和使用-difftime 进行real 差异计算。
  • 作为一个粗略的例子,2021-10-192021-Jan 之间的(确切地说)区别是什么?我将其概括为一个月而不是一周,但要点是一样的。该值介于 261​​ 和 291(含)之间,并且鉴于我们所知道的,它可能是任何具有相同概率的值。如果我们假设某人最有可能想要与第一天或最后一天的差异,那么它是 261 或 291 中的一个,但要知道我们需要知道哪一个原始问题的意图和/或上下文。

标签: r data.table lubridate


【解决方案1】:

不能以固定单位计算日期和星期之间的差异,它们是不同的。最好的办法是确定一个范围,其中的差异可能是一个数字加或减 3.5,以表明您不知道哪个值是正确的。如果假设您的“周”从星期日或星期一或您选择的任何一天开始,那么......将t0 更改为Date(永久,作为新列,或即时)和使用-difftime 进行真正的差异计算。

作为一个粗略的例子,2021-10-192021-Jan 之间(确切地说)有什么区别?我将其概括为一个月而不是一周,但要点是一样的。该值介于 261​​ 和 291(含)之间,并且根据我们所知道的,它可能是任何具有相同概率的值。如果我们假设某人最有可能想要与该月的第一天或最后一天的差异,那么它是 261 或 291 之一,但要知道我们需要知道原始问题的意图和/或上下文。

有关“如何将年月转换为Date 对象”的讨论,请参阅Transform year/week to date object

这里有两个选项,具体取决于星期天或星期一。 (我之所以选择这两天,是因为它们似乎是最频繁的一周开始日;但是,无论您使用哪一天,都取决于您和上下文或您的数据,我不断言这些日子比其他日子更好。)

library(data.table)
data[, t0_sun := as.Date(sprintf("%4i%02i7", t0_year, t0_week), format = "%Y%U%u")
  ][, t0_mon := as.Date(sprintf("%4i%02i1", t0_year, t0_week), format = "%Y%U%u")
  ][, d := as.numeric(t1_date - t0_sun, "weeks")]
#       id t0_year t0_week    t1_date     t0_mon     t0_sun         d
#    <int>   <num>   <num>     <Date>     <Date>     <Date>     <num>
# 1:     1    2000       4 2010-07-31 2000-01-24 2000-01-23 548.85714
# 2:     2    2001      32 2010-12-31 2001-08-13 2001-08-12 489.71429
# 3:     3    2002      44 2010-02-08 2002-11-04 2002-11-03 379.14286
# 4:     4    2001      15 2005-07-05 2001-04-16 2001-04-15 220.28571
# 5:     5    2000      11 2000-07-20 2000-03-13 2000-03-12  18.57143

(我计算了t0_sunt0_mon 只是为了演示星期天和星期一的计算,注意附加到字符串的不同数字。你只需要一个。)

请注意,从?strptime(以及链接到Date 的问题/答案到Date),"%U" 使用的是美国标准;有人可能会选择"%W" 用于英国的周。

data[, t0_sun := as.Date(sprintf("%4i%02i0", t0_year, t0_week), format = "%Y%W%w")
  ][, t0_mon := as.Date(sprintf("%4i%02i1", t0_year, t0_week), format = "%Y%W%2")
  ][, d := as.numeric(t1_date - t0_sun, "weeks")]

【讨论】:

  • 这是有道理的。如果 t1 也是年和周,例如。数据
  • 如果t1t2 都采用年/周格式,假设每个日期相同,那么我认为你 仍然需要以与上述相同的方式使用as.Date(使用"%U""%W",您的选择)。 (当然,通过使用年和每年的周数等来尝试模数数学来解决它当然是可行的,并且......它涉及足够多的例外规则,在某些时候很容易最终变得不准确。真的,使用了解规则并经过测试的库。转换为Date,使用简单的减法,然后继续处理下一个大问题:-)
  • 当然,你不需要存储临时的Date对象,你可以做difftime(as.Date(sprintf(...)), as.Date(sprintf(...)), units="weeks")或类似的。但仍应创建临时对象。
【解决方案2】:

这行得通吗:

library(dplyr)
library(lubridate)

data %>% mutate(t0_date = as.Date(paste(t0_year, round(day(weeks(t0_week))/30), '01', sep = '-'), format = '%Y-%m-%d'), diff_weeks = difftime(t1_date,t0_date, units = 'weeks'))
   id t0_year t0_week    t1_date    t0_date      diff_weeks
1:  1    2000       4 2010-07-31 2000-01-01 552.00000 weeks
2:  2    2001      32 2010-12-31 2001-07-01 495.71429 weeks
3:  3    2002      44 2010-02-08 2002-10-01 383.85714 weeks
4:  4    2001      15 2005-07-05 2001-04-01 222.28571 weeks
5:  5    2000      11 2000-07-20 2000-03-01  20.14286 weeks

【讨论】:

    猜你喜欢
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    • 2013-09-05
    • 2023-03-10
    相关资源
    最近更新 更多