遍历月份并计数行

时间:2018-08-23 13:25:24

标签: r

我有一个包含三列的df:StartDate,EndDate和SubscriptionType。

<p id="code"></p> <form action="/create-beta.php" method="post"> <input type="hidden" name="curl" id="curl"> <br>

例如,通过使用以下代码:

df = data.frame(StartDate = as.Date(c('2018-05-01', '2018-06-01', '2018-01-01', '2018-07-01', '2018-03-01')),
                EndDate = as.Date(c('2019-04-30', '2019-05-31', '2018-12-31', '2019-06-30', '2019-02-28')),
                SubscriptionType = c('monthly', 'monthly', 'yearly', 'yearly', 'yearly'))

我得到5月份活跃的订阅数。

我想打印2018年每个月的结果并将其存储在数据框中。

到目前为止,我尝试使用此代码:

df %>% filter(StartDate <= ymd('2018-5-15') & EndDate >= ymd('2018-5-15')) %>% count()

但是我得到的是24条警告和一个仅填充零的数据框z。

任何帮助将不胜感激,谢谢!

4 个答案:

答案 0 :(得分:1)

我们可以使用map进行分组。使用Date将'm'创建为paste类对象,然后根据条件filter创建数据集并应用count

m <- ymd(paste0('2015-', sprintf('%02d', 1:12), '-15'))
map_df(m, ~ 
       df %>%      
         filter(Start_Date <=  .x & EndDate  >= .x) %>% 
         count)

答案 1 :(得分:1)

ymd('2018-i-15')不会产生date对象。您已传递ymd()的字符串,该字符串的年份为2018,月份为i,日期为15。在这种情况下,i是固定的,不能由循环变量i代替。这就是为什么出现错误All formats failed to parse. No formats found.的原因,该错误实际上是在告诉您它无法标识以i作为月份的日期。

要保留i的变量,请尝试ymd(paste0("2018-", i, "-15"))

for (i in m) {
     z = rbind(z, data.frame(df %>% filter(StartDate <= ymd(paste0("2018-", i, "-15")) & EndDate >= ymd(paste0("2018-", i, "-15"))) %>% count()))
}

答案 2 :(得分:1)

改进@akrun的答案,可以为循环问题提供最简单直接的解决方案。

但是,如果您希望在两个月份之间的间隔重叠的任何月份获得TRUE,最好将它们转换为月份,而不要使用固定的日期。您可以针对包含'2018-05-16''2018-06-14'(分别为开始和结束日期)的某行进行测试,对于具有原始条件的'2018-05'来说,它都不会计入'2018-06'

f <- '%Y-%m'  # it'll be used a few times

m <- seq(ymd(180101), ymd(191231), by='month')
m <- format(m, f)  # 'e.g. 2018-05'

# purrr::map_dfr() works like apply, it'll map each value from m into .x
# inside the expression and use dplyr::bind_rows() to concatenate the
# resulting rows (see documentation for details).
map_df(m, ~ df %>%
        filter(format(StartDate, f) <=  .x &
                format(EndDate, f)  >= .x) %>%
        group_by(month = .x) %>%
        count()
)

# For the data.frame you provided this is the result:
## A tibble: 18 x 2
## Groups:   month [18]
#   month       n
#   <chr>   <int>
# 1 2018-01     1
# 2 2018-02     1
# 3 2018-03     2
# 4 2018-04     2
# 5 2018-05     3
# 6 2018-06     4
# 7 2018-07     5
# 8 2018-08     5
# 9 2018-09     5
#10 2018-10     5
#11 2018-11     5
#12 2018-12     5
#13 2019-01     4
#14 2019-02     4
#15 2019-03     3
#16 2019-04     3
#17 2019-05     2
#18 2019-06     2  

答案 3 :(得分:0)

使用dplyr的解决方案。

一些获取日期数据框的示例数据:

library(tidyverse)
library(lubridate)

df <- tibble(as.Date(c("2018-05-02", "2018-05-03", "2018-05-04", "2018-05-04", "2018-05-02", "2018-06-03", "2018-06-04", "2018-07-04", "2018-07-04"))) %>%
    rename(Date = 1)

添加指定数字月份的列:

df <- df %>% 
mutate(Month = month(Date))

创建一个数字月份(1到12)的数据框,并在其空白列中列出称为“订阅数”的订阅数。

subs_by_month <- as.tibble(1:12) %>% 
    rename(Month = 1)
subs_by_month$subs <- NA

使用tally来计数观察次数:

for(i in 1:12){
  subs_by_month$subs[[i]] <- unlist(
    df %>%
    tally(Month==i)
    )
}

结果框架具有数字月份和该月的订阅数。