对于两个不同的年份,我需要对每年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解决方案少一行:(
- 使用
lubridate
包的ymd
函数将字符类型转换为最新 - 使用
DayMonth
函数时,按月和日仅考虑所需间隔的月和日 - 按
year
分组 - 过滤间隔
- 总结
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"中获取month
和day
,用ISOdate
创建一个新日期,year
标准化为一年(这里我们选择了2021,但它可以是任何一年(,然后用between
filter
指定"newdate",并指定left
和right
参数作为自定义日期范围,然后按"年份"分组,在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
- 然后用
10000
对date
的%%
进行模除法过滤,获得最后四位数字,并检查您的条件 - 最后总结
- 如果您的日期列是字符类型,请在所有步骤中使用
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