使用R,对于每年,我需要对同一个日期之间不同年份的销售额求和



对于两个不同的年份,我需要对每年1月3日至3月3日的所有销售额进行汇总。我更喜欢dplyr解决方案。

我在stackoverflow中查看的所有可能的解决方案都使用SQL,而不是R。如果有人知道我遗漏了一个解决方案,请告诉我。

在R中,我知道如何使用组和各种dplyr函数,但我需要帮助来完成这篇文章。

我希望输出看起来像这样:

Year   Total Sales
2020   138 
2021   196

输入

df <- data.frame(date=c(20200102, 20200107, 20200210, 20200215, 20200216, 20200302, 20200305, 20210101, 20210104, 20210209, 20210211, 20210215, 20210317, 20210322),
sales=c(9,14,27,30,33,34,36,44,45,47,51,53,56,58))

比我的主akrun解决方案少一行:(

  1. 使用lubridate包的ymd函数将字符类型转换为最新
  2. 使用DayMonth函数时,按月和日仅考虑所需间隔的月和日
  3. year分组
  4. 过滤间隔
  5. 总结
library(lubridate)
df %>% 
mutate(date = ymd(date)) %>% 
mutate(DayMonth = format(as.Date(date), "%m-%d")) %>% 
group_by(Year=year(date)) %>% 
filter(DayMonth>"01-03" & DayMonth<"03-03") %>% 
summarise(Total_Sales = sum(sales))

输出:

Year Total_Sales
<int>       <dbl>
1  2020         138
2  2021         196

您也可以使用以下解决方案:

library(dplyr)
library(lubridate)
df %>%
mutate(date = ymd(date)) %>%
group_by(year = year(date)) %>%
filter(date %within% interval(ymd(paste(first(year), "01-03", sep = "-")), 
ymd(paste(first(year), "03-03", sep = "-")))) %>%
summarise(sale = sum(sales))
# A tibble: 2 x 2
year  sale
<dbl> <dbl>
1  2020   138
2  2021   196

我们可以使用tidyverse。将"date"转换为Date类(lubridate中的ymd(,从"date"中获取monthday,用ISOdate创建一个新日期,year标准化为一年(这里我们选择了2021,但它可以是任何一年(,然后用betweenfilter指定"newdate",并指定leftright参数作为自定义日期范围,然后按"年份"分组,在summarise中获得"销售额"的sum

library(dplyr)
library(lubridate)
df %>%
mutate(date = ymd(date), year = year(date),
month = month(date), day = day(date), 
newdate = as.Date(ISOdate(2021, month, day))) %>% 
filter(between(newdate, as.Date("2021-01-03"), 
as.Date("2021-03-03"))) %>% 
group_by(year) %>%
summarise(sales = sum(sales))

-输出

# A tibble: 2 x 2
#   year sales
#  <dbl> <dbl>
#1  2020   138
#2  2021   196

或使用base R中的aggregate。通过sub位置创建"newdate",即删除"date"开头(^(的前4个字符(.{4}(,替换为"2021",转换为Date类,使用关系运算符执行subset。然后使用aggregate中的过滤数据集,通过year部分获得"销售"的sum,即前4个字符

subdf <- subset(transform(df, newdate = as.Date(sub("^.{4}", "2021", 
date), '%Y%m%d')),
newdate >= as.Date('2021-01-03') & newdate <= as.Date('2021-03-03'))
aggregate(sales ~ cbind(Year = substr(date, 1, 4)), subdf, FUN = sum)
#  Year sales
#1 2020   138
#2 2021   196

一个仅使用整数/模除法的简单解决方案,%%&%/%,即不使用任何日期类型库(lubridate等(

  • 由于您的日期变量遵循最符合逻辑(最适合对日期进行实用排序(的格式,因此这里的工作是检查前四位的条件/分组,过滤最后四位并进行总结。所以
  • Year上的group_by,它是通过整数除法获得的,即%/%日期除以10000,它将始终给您前四位数字(如果是YYYYMMDD格式(
  • 无需先创建此列,然后再创建group_by
  • 然后用10000date%%进行模除法过滤,获得最后四位数字,并检查您的条件
  • 最后总结
  • 如果您的日期列是字符类型,请在所有步骤中使用as.numeric进行包装
library(dplyr)
df %>% 
group_by(Year = date %/% 10000) %>%
filter(date %% 10000 > 103, date %% 10000 < 303) %>%
summarise(Total_sales = sum(sales))
#> # A tibble: 2 x 2
#>    Year Total_sales
#>   <dbl>       <dbl>
#> 1  2020         138
#> 2  2021         196

创建于2021-05-30由reprex包(v2.0.0(


等效baseR语法

aggregate(sales ~ cbind(Year = date %/% 10000), 
subset(df, date %% 10000 > 103 & date %% 10000 < 303), 
FUN = sum)
Year sales
1 2020   138
2 2021   196

最新更新