【问题标题】:Using R, for each year, I need to sum the sales in different years between same two dates使用 R,对于每一年,我需要将相同两个日期之间不同年份的销售额相加
【发布时间】:2021-08-17 16:07:59
【问题描述】:

对于两个不同的年份,对于每一年,我需要汇总从 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))

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    比我大师 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
    

    【讨论】:

    • 点赞了亲爱的@TarJae,你可以进一步缩短至少一行,df %&gt;% group_by(Year = year(ymd(date))) %&gt;% mutate(DayMonth = format(ymd(date), "%m-%d")) %&gt;% filter(DayMonth &gt; "01-03" &amp; DayMonth &lt; "03-03") %&gt;% summarise(Total_Sales = sum(sales))
    【解决方案2】:

    您还可以根据您的目的使用以下解决方案:

    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
    

    【讨论】:

    • 非常好!甚至少一排:)
    • 你真是太好了,我的朋友。我知道这很不寻常,想尝试采用这种形式与你们已经发布的不同。
    【解决方案3】:

    我们可以使用tidyverse。将“日期”转换为Date 类(ymd 来自lubridate),从“日期”获取monthday,使用ISOdate 创建一个新日期,并将year 标准化为一年(这里我们选择 2021 - 虽然它可以是任何一年),然后我们使用 between filter '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 Raggregate。通过subsitution 创建'newdate' 即删除'date' 开头(^)的前4 个字符(.{4}),替换为'2021',转换为Date 类,执行subset 与关系运算符。然后使用aggregate 中的过滤数据集通过year 部分(即前4 个字符)获取'sales' 的sum

    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
    

    【讨论】:

      【解决方案4】:

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

      • 由于您的日期变量遵循最符合逻辑(并且最适合日期的 aplhabetical 排序)的格式,因此这里的工作是检查前四位数字的条件/分组,过滤后四位数字并进行总结。所以
      • group_by on Year 是通过整数除法获得的,即 %/% 日期除以 10000 将始终为您提供前四位数字(在 YYYYMMDD 格式的情况下)
      • 无需先创建此列再创建group_by
      • 然后使用 date 的模除法 %% 通过 10000 过滤行中的最后四位数字并检查您的条件
      • 最后总结一下
      • 如果您的日期列是字符类型,请在所有步骤中用 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
      

      reprex package (v2.0.0) 于 2021 年 5 月 30 日创建


      等价的 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
      

      【讨论】:

      • 太棒了!感谢您提出这个概念!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多