【问题标题】:Converting daily transaction data to the sum of the end of each week将每日交易数据转换为每周结束的总和
【发布时间】:2020-04-16 10:21:51
【问题描述】:

我有每日交易数据,我想将其转换为每周总和(即截至周日的那一周的每周交易总和)。

目前的结构是这样的

dataset <- data.frame(date=as.Date(c("20200407", "20200407", "20200407", "20200407"), "%Y%m%d"), category=c("Petrol Station", "Accomodation", "Discount Store", "Shopping"), amount=c(5431.47, 839.1, 2399.13, 1305.82))

  • 日期 - 基本上是当天所有不同的交易(我已经使用 ydm 函数重新格式化)
  • 类别 - 不同类型的支出
  • 金额 - 是支出。

    date        category        amount
    2020-04-07  Petrol Station  5431.47
    2020-04-07  Accommodation   839.1
    2020-04-07  Discount Store  2399.13
    2020-04-07  Shopping        1305.82
    

总共有大约 10 万行超过 3 年的数据

我可以使用下面的(给我 W1、W2、...等)创建一个星期变量,并通过对其进行分组来求和。但是,它在第​​ 1 周和第 52 周似乎无法正常工作,因为没有完整的 7 天

dataset$Week <- strftime(dataset$date, format = "%Y-W%V")

任何建议将不胜感激。

【问题讨论】:

    标签: r


    【解决方案1】:

    在您的示例中使用 data.table 和 lubridate 包:

    library(lubridate)
    library(data.table)
    # convert data.frame to data.table
    setDT(dataset)
    # add week variable, then sum grouping by week and category 
    dataset[, week := week(date)][, 
      wkSum = sum(amount), keyby = c("week", "category")]
    

    稍微修改您的示例数据以涵盖多周和重复的类别以表明它有效,此输入

             date       category  amount
    1: 2020-04-06       Shopping 1203.54
    2: 2020-04-07 Petrol Station 5431.47
    3: 2020-04-07       Shopping 1305.82
    4: 2020-04-08       Shopping 1400.43
    

    给出输出

       week       category   wkSum
    1:   14 Petrol Station 5431.47
    2:   14       Shopping 2509.36
    3:   15       Shopping 1400.43
    

    【讨论】:

      【解决方案2】:

      试试这个:

      library(tidyverse)
      library(lubridate)
      
      dataset%>%
        mutate(week = week(date))%>%
        group_by(week)%>%
        summarize(week_sum = sum(amount))
      

      如果您想获得一个 etxtra “类别”- 评估比:

      dataset%>%
        mutate(week = week(date))%>%
        group_by(week, category)%>%
        summarize(week_category_sum = sum(amount))
      

      编辑:

      @TobKel 类似的东西 - 但对于类别列中的每个单独的子类别(大约有 100 个)。

      我可以生成以下罚款,只是第 01 周和第 52 周没有完整的 7 天

      【讨论】:

      • 这似乎给了我一个输出。理想情况下,我希望在 2 年内为每个子类别获得每周总和(到周日的 7 天总和)。 IE。对于每个子类别,我将有 52 周的一周数据,总和到周日的 7 天。
      • 那么你需要做的是事先进行一些数据整理。例如:dataset %&gt;% mutate(week = week(date)) %&gt;% spread(., category, amount)
      • @Josh 你能举例说明你想要的输出吗?
      • @TobKel 类似这样的东西 - 但对于类别列中的每个单独的子类别(大约有 100 个)。我可以生成以下罚款,它只是第 01 周和第 52 周,其中没有完整的 7 天 周类别数量 2018-W01 食品/饮料 >> 快餐 9091946.07 2018-W02 食品/饮料 >> 快餐8242358.22 2018-W03 食品/饮料 >> 快餐 8609234.22 2018-W04 食品/饮料 >> 快餐 8340712.86 2018-W05 食品/饮料 >> 快餐 8084297.38 2018-W06 食品/饮料 >> 快餐 8235502.35 2018-W0饮品 >> 快餐 8373676.62
      【解决方案3】:

      @TobKei 的贡献很棒,您只需稍微更改数据集的结构即可实现所需的功能。本质上,您需要将每个类别的值作为一个变量,以便能够生成每周总和而不是一个单一的数字。您可能想尝试以下方法:

      library(tidyverse)
      library(dplyr)
      library(lubridate)
      
      sum_output <- dataset %>%
        mutate(week = week(date)) %>%
        spread(., category, amount) %>%
        group_by(week) %>%
        summarise(accomodation_week_sum = sum(Accomodation), 
               discount_store_week_sum= sum(`Discount Store`), 
               Petrol_week_sum=sum(`Petrol Station`), 
               shopping_week_sum= sum(Shopping))
      

      目前它是相同的数字,因为您在同一周没有更多观察结果,但最终如果您有更多观察结果,group_by() 将每周返回给您一笔款项。

      更新:如果您有数百个您显然不想单独输入的类别,则以下方法应该有效:

      library(tidyverse)
      library(dplyr)
      library(lubridate)
      
      sum_output <- dataset %>%
        mutate(week = week(date)) %>%
        split(.$category) %>%
        lapply(., group_by, week) %>%
        lapply(., summarise, week_sum_amount=sum(amount)) %>%
        bind_rows(., .id = "week_sum_amount") %>% 
        data.frame(check.names = FALSE)
      

      主要添加的是split(),它将您在一个列表中的不同数据框中的所有类别分开。数据框列表。

      【讨论】:

      • 酷 - 看起来不错。大约有 400 个子类别,有没有简单的方法来转换它们?
      • 谢谢@yach 这似乎让我离我更近了,但它提供了大约 400 个数据名,每个数据名有一行和一列(正确地加总了总体总数)。我怀疑我需要按周进行不同的群组功能?
      • 对于当前形式的数据集,您不需要另一个 group_by。它返回 2 列和与周数一样多的行。以如下数据集为例:
      • dataset &lt;- data.frame(date=as.Date(c("20200407", "20200407", "20200407", "20200407", "20200406", "20200406", "20200406", "20200408", "20200408", "20200408", "20200408", "20200408"), "%Y%m%d"), category=c("Petrol Station", "Accomodation", "Discount Store", "Shopping", "Petrol Station", "Accomodation", "Discount Store", "Shopping", "Petrol Station", "Accomodation", "Discount Store", "Shopping"), amount=c(5431.47, 839.1, 2399.13, 1305.82, 2000, 1800, 3500, 1670, 1500, 1400, 2900, 2000)) 和你最初的一样,但我在两周前添加了更多观察结果。
      • 如果在我提出的解决方案中添加:sum_output &lt;- sum_output %&gt;% bind_rows(., id="week_sum_amount") %&gt;% data.frame( check.names=FALSE) 然后它将再次将所有 400 个数据帧合并为一个。您可以选择对您的流程更方便的方法。
      猜你喜欢
      • 1970-01-01
      • 2020-07-06
      • 2018-01-24
      • 1970-01-01
      • 1970-01-01
      • 2021-08-23
      • 2020-06-13
      • 2016-01-29
      • 2021-04-28
      相关资源
      最近更新 更多