【问题标题】:counting days between two date columns by which quarter they fall into计算两个日期列之间的天数,它们属于哪个季度
【发布时间】:2015-05-06 22:29:27
【问题描述】:

我有一个数据集,其中包括以下两列。他们指的是病假。

df <- data.frame(BEGIN_DT = c("04/12/2013", "14/01/2013", "31/12/2012", "24/09/2013", "31/12/2013"),
           END_DT = c("04/12/2013", "15/01/2013", "04/01/2013", "27/09/2013",  "31/12/2013"))
rownames(df) <- c(16:20)

     BEGIN_DT     END_DT
16 04/12/2013 04/12/2013
17 14/01/2013 15/01/2013
18 31/12/2012 04/01/2013
19 24/09/2013 27/09/2013
20 31/12/2013 31/12/2013

我要做的是根据 BEGIN_DT 和 END_DT 值制作五个额外的列,(Q1、Q2、Q3、Q4、Total)计算每个季度的病假天数。

例如第 18 行:

  BEGIN_DT       END_DT  Q1  Q2  Q3  Q4  Total
31/12/2012   04/01/2013   4   0   0   1      5

我看过这里,这似乎算总数,但我真的不知道如何将这些分成四等份。

calculating number of days between 2 columns of dates in data frame 2-columns-of-dates-in-data-frame

survey <-     data.frame(date=c("2012/07/26","2012/07/25"),tx_start=c("2012/01/01","2012/01/01    "))

survey$date_diff <- as.Date(as.character(survey$date), format="%Y/%m/%d")-
                  as.Date(as.character(survey$tx_start), format="%Y/%m/%d")
survey

目前,我有以下代码,但它只给了我第一季度的总天数,其余的留空。我正在从结束日期中减去开始日期,但是在过去一周的许多小时之后,我并没有更接近(或者可能更远离)弄清楚如何填充新的季度列。

sick2$Q1 <- if ("/%m/" < 4) {
  as.Date(as.character(sick2$END_DT), format="%d/%m/%Y") -
  as.Date(as.character(sick2$BEGIN_DT), format="%d/%m/%Y")  
} else { "0" }
sick2$Q2 <- if ("/%m/" > 3 & "/%m/" < 7) {
  as.Date(as.character(sick2$END_DT), format="%d/%m/%Y") -
  as.Date(as.character(sick2$BEGIN_DT), format="%d/%m/%Y")
} else { "0" }
sick2$Q3 <- if ("/%m/" > 6 & "/%m/" < 10) {
  as.Date(as.character(sick2$END_DT), format="%d/%m/%Y") -
  as.Date(as.character(sick2$BEGIN_DT), format="%d/%m/%Y")
} else { "0" }
sick2$Q4 <- if ("/%m/" > 9) {
  as.Date(as.character(sick2$END_DT), format="%d/%m/%Y") -
  as.Date(as.character(sick2$BEGIN_DT), format="%d/%m/%Y")
} else { "0" }

无论如何,如果有人至少可以在这里为我指出正确的方向,我会 v.v.v.非常感谢,谢谢,阿德里安。

【问题讨论】:

标签: r lubridate


【解决方案1】:

不漂亮(eww.. 循环),但这是我的看法:

require(lubridate)
df <- data.frame(BEGIN_DT = c("04/12/2013", "14/01/2013", "31/12/2012", "24/09/2013", "31/12/2013"),
           END_DT = c("04/12/2013", "15/01/2013", "04/01/2013", "27/09/2013",  "31/12/2013"))
rownames(df) <- c(16:20)
df$BEGIN_DT <- as.Date(df$BEGIN_DT, "%d/%m/%Y")
df$END_DT <- as.Date(df$END_DT, "%d/%m/%Y")

for(i in 1:5){
  diff_time <- as.numeric(df$END_DT[i] - df$BEGIN_DT[i])
  date_vec <- df$BEGIN_DT[i]
  for(j in 1:diff_time){
    if(diff_time > 0) {
    date_vec <- c(date_vec, df$BEGIN_DT[i] + j)
    }
  }
  date_vec <- as.character(quarters(date_vec))
  df$Q1[i] <- length(date_vec[date_vec %in% "Q1"])
  df$Q2[i] <- length(date_vec[date_vec %in% "Q2"])
  df$Q3[i] <- length(date_vec[date_vec %in% "Q3"])
  df$Q4[i] <- length(date_vec[date_vec %in% "Q4"])
}

首先要做的是累积包含在间隔中的所有日期的向量,然后对照lubridatequarters()检查它,然后计算出现次数。想不出没有循环的方法。也许其他人可以?

【讨论】:

  • 非常感谢 A.Val 的想法。谢谢.. 现在玩你可爱的循环 :) 我正在采取婴儿步骤,并且肯定会尽快更新我的位置。
【解决方案2】:

对此并不感到自豪,但可能会给你一些方向。一定有更好的方法...

library(lubridate)
library(plyr)

df <- data.frame(BEGIN_DT = c("04/12/2013",
                               "14/01/2013",
                               "31/12/2012",
                               "24/09/2013",
                               "31/12/2013"),
                 END_DT = c("04/12/2013",
                             "15/01/2013",
                             "04/01/2013",
                             "27/09/2013",
                             "31/12/2013"))

df$BEGIN_DT <- dmy(df$BEGIN_DT)
df$END_DT <- dmy(df$END_DT)

date_seq <- list()
for (i in seq_along(df$BEGIN_DT)) {
  date_seq[[i]] <- seq(from = df$BEGIN_DT[i], 
                       to   = df$END_DT[i], 
                       by   = "1 day")
}

# sapply(date_seq, quarter)
sapply(sapply(date_seq, quarters), table)
results <- sapply(sapply(date_seq, quarters), table)

ldply(results rbind)
#   Q4 Q1 Q3
# 1  1 NA NA
# 2 NA  2 NA
# 3  1  4 NA
# 4 NA NA  4
# 5  1 NA NA

cbind(df, ldply(results, rbind))
#     BEGIN_DT     END_DT Q4 Q1 Q3
# 1 2013-12-04 2013-12-04  1 NA NA
# 2 2013-01-14 2013-01-15 NA  2 NA
# 3 2012-12-31 2013-01-04  1  4 NA
# 4 2013-09-24 2013-09-27 NA NA  4
# 5 2013-12-31 2013-12-31  1 NA NA

library(magrittr) 的替代解决方案

仍然需要date_seq 列表对象

library(magrittr)

sapply(date_seq, quarters) %>%
  sapply(., factor, levels=c("Q1", "Q2", "Q3", "Q4")) %>%
  sapply(., table) %>%
  t(.) %>%
  cbind(df, .)

#     BEGIN_DT     END_DT Q1 Q2 Q3 Q4
# 1 2013-12-04 2013-12-04  0  0  0  1
# 2 2013-01-14 2013-01-15  2  0  0  0
# 3 2012-12-31 2013-01-04  4  0  0  1
# 4 2013-09-24 2013-09-27  0  0  4  0
# 5 2013-12-31 2013-12-31  0  0  0  1

【讨论】:

  • 感谢 Jason(也感谢编辑建议)。我很惊讶你们想知道更好的方法 - 让我担心我承担的这个项目:p 同样,一旦我得到值得报告的地方,我会尽快向你们更新我的进展
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-26
  • 2019-09-27
  • 2015-05-05
相关资源
最近更新 更多