【问题标题】:R: Monthly bins based on source date rangesR:基于源日期范围的每月 bin
【发布时间】:2017-08-21 11:10:44
【问题描述】:

我发现的 R 分箱示例似乎假设源数据有一个日期(或日期/时间)。我为 2002-2017 年的用户帐户设置了离散的开始和停止日期。我想在 2002-17 年的整个范围内使用每月的垃圾箱输出活跃帐户的数量。

数据目前在 dd/mm/yyyy 字符串中,但如果需要我可以轻松更改该格式;行按开始日期升序排序。例如

Start       Stop
04/09/2006  23/01/2014
...
06/07/2008  11/03/2017
...
30/09/2010  22/04/2016

结果计数将是,例如:

Mar 2006    0
Jan 2007    1
Mar 2011    3
Jun 2015    2
Sep 2016    1
...etc.

生成计数的目的是绘制一段时间内的总活跃帐户。我愿意接受每日计数,然后按月汇总(如果更容易的话)。不过,我一开始就卡住了:bin,其中源是日期范围而不是单个日期。

【问题讨论】:

  • 那你现在想做什么?你试过了吗?
  • 嗯,类似于下面公认的解决方案。谢谢

标签: r date


【解决方案1】:

将列转换为"yearmon" 类并使用mapply 生成ym 覆盖的年/月。然后计算每年/每月发生的次数,并将其与具有 2002 年 1 月至 2017 年 12 月之间所有年份/月份的数据框合并,给出M_na,并将 NA 替换为 0,给出M

library(zoo)

DF2 <- transform(DF, Start = as.yearmon(Start), Stop = as.yearmon(Stop))

ym <- unlist(mapply(seq, DF2$Start, DF2$Stop, MoreArgs = list(by = 1/12)))
Ag <- aggregate(ym^0, list(ym = as.yearmon(ym)), sum)

M_na <- merge(Ag, data.frame(ym = as.yearmon(seq(2002, 2017+11/12, 1/12))), all.y = TRUE)
M <- transform(M_na, x = replace(x, is.na(x), 0))


plot(x ~ ym, M, type = "h", xlab = "", ylab = "Count", xaxt = "n")
axis(1, 2002:2017)

(续图)

ma​​grittr

这也可以表示为这样的 magrittr 管道:

library(magrittr)
library(zoo)

M <- DF %>%
   transform(Start = as.yearmon(Start), Stop = as.yearmon(Stop)) %$%
   unlist(mapply(seq, Start, Stop, MoreArgs = list(by = 1/12))) %>%
   { aggregate(.^0, list(ym = as.yearmon(.)), sum) } %>%
   merge(data.frame(ym = as.yearmon(seq(2002, 2017+11/12, 1/12))), all.y = TRUE) %>%
   transform(x = replace(x, is.na(x), 0))

注意:我们假设以下输入带有 Date 类列:

Lines <- "
Start       Stop
04/09/2006  23/01/2014
06/07/2008  11/03/2017
30/09/2010  22/04/2016"
DF <- read.table(text = Lines, header = TRUE)
fmt <- "%d/%m/%Y"
DF <- transform(DF, Start = as.Date(Start, fmt), Stop = as.Date(Stop, fmt))

【讨论】:

  • 再次感谢。顺便说一句,使用您的原始解决方案,除了一个明显的故障外,所有工作都有效。从 7 月 17 日到 17 月 17 日的箱子的计数值都应该为零,但每个都有一个值。相比之下,Jan-02 到 Nov-02 的计数为零。我假设前者是我数据中的错误,但任何记录中的最新日期是 30/6/17。奇怪的。尽管如此,还是很高兴能走到这一步。
  • tail(M) 显示,与您的评论相反,7 月 17 日至 12 月 17 日为零。建议您开始一个新的 R 会话,将代码粘贴到答案末尾的注释中,然后将代码粘贴到答案正文中,然后运行 ​​tail(M)。
  • 谢谢。一个新的会议似乎清除了这个错误。 (用户错误,我忘记使用更正版本重新加载数据 - 2017 年末的错误计数是我原始数据集中的实际错误。)。感谢您的帮助。
【解决方案2】:

如果您将日期格式化为月-年,然后应用一个包含所有月-年值的因子,您应该会得到您想要的

# creating data for example
dates <- sample(seq(as.Date('01/01/2002', format='%m/%d/%Y'), 
                    as.Date('12/31/2017', format='%m/%d/%Y'), 
                    by="day"), 30)

# use the cut function to round up to the first of each month if you like
months <- format(as.Date(cut(dates, breaks= 'month')), '%b %Y')
# cut function is not necessary if you prefer to skip to the format
months <- format(dates, '%b %Y')

# Created an ordered vector of months and years
ord_months <- c('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 
                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
ord_year <- as.character(2002:2017)
# create an ordered vector of month years
months_ordered <- apply(expand.grid(ord_months, ord_year), 1, paste, collapse = ' ')
head(months_ordered)

# factor the format and apply the factored vector as the levels
monthsF <- factor(months, levels=months_ordered)
table(monthsF)

【讨论】:

  • 谢谢。我已经采用了上述方法(因为我需要其他地方的日组件),但您的建议是一个有用的替代方案。
猜你喜欢
  • 2013-03-09
  • 1970-01-01
  • 2017-02-23
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
  • 2021-02-20
  • 1970-01-01
相关资源
最近更新 更多