【问题标题】:Row-based calculation of current sum of multiple columns in time series基于行计算时间序列中多列的当前总和
【发布时间】:2018-12-30 16:56:49
【问题描述】:

我正在查询具有以下结构的数据库:

df <- data.frame(id = c(1, 2, 2, 1, 2),
             type = c("A", "B1", "B2", "A", "B1"),
             date = as.POSIXct(c("2018-07-23 6:00", "2018-07-23 6:12", 
                                 "2018-07-23 6:25", "2018-07-23 10:00", 
                                 "2018-07-23 10:30")),
             value = c(5, 2, 3, 7, 4))

  id type                date value
1  1    A 2018-07-23 06:00:00     5
2  2   B1 2018-07-23 06:12:00     2
3  2   B2 2018-07-23 06:25:00     3
4  1    A 2018-07-23 10:00:00     7
5  2   B1 2018-07-23 10:30:00     4

date 变量表示对数据库进行更改的时间。我的目标是重新格式化数据框,使我能够识别每行/新条目的 value 变量的条目总和。在计算总和时,每当出现该类别的新条目时,都需要替换 type 变量中所有类别的值。

这是预期的输出:

  id type                date value combined_value
1  1    A 2018-07-23 06:00:00     5              5
2  2   B1 2018-07-23 06:12:00     2              7
3  2   B2 2018-07-23 06:25:00     3             10
4  1    A 2018-07-23 10:00:00     7             12
5  2   B1 2018-07-23 10:30:00     4             14

前三行中combined_value的值只是value的总和,第四行中type == "A"的值从5变为7并且必须替换,但@987654329的值@ 和 type == "B2" 保持不变。但是,type == "B1" 第五行发生了变化,因此在计算 combined_value 中的总和时必须替换。

到目前为止,我已经成功地使用group_by()filter()summarise() 的组合来计算预定义时间点的总和。但是,我希望能够使用一个数据框来跟踪一年多来所做的所有更改,该数据框将所有条目存储在行中,并包含有关type 中各个类别的当前总和的信息。

编辑:@jaySf 提供的解决方案适用于提供的示例数据。然而,我的实际数据集有大量需要计算当前总和的组。这是反映结构的更新数据框,id 表示组索引:

df <- data.frame(id = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2),
             type = c("A", "B1", "B2", "A", "B1", 
                      "A", "A", "B2", "B3", "A"),
             date = as.POSIXct(c("2018-07-23 6:00", "2018-07-23 6:12", 
                                 "2018-07-23 6:25", "2018-07-23 10:00", 
                                 "2018-07-23 10:30")),
             value = c(5, 2, 3, 7, 4, 3, 5, 1, 2, 7))

相应地,预期的输出将是:

   id type                date value combined_value
1   1    A 2018-07-23 06:00:00     5              5
2   1   B1 2018-07-23 06:12:00     2              7
3   1   B2 2018-07-23 06:25:00     3             10
4   1    A 2018-07-23 10:00:00     7             12
5   1   B1 2018-07-23 10:30:00     4             14
6   2    A 2018-07-23 06:00:00     3              3
7   2    A 2018-07-23 06:12:00     5              5
8   2   B2 2018-07-23 06:25:00     1              6
9   2   B3 2018-07-23 10:00:00     2              8
10  2    A 2018-07-23 10:30:00     7             10

我尝试使用tapply 为我的群组计数,但无法让代码正常工作。

【问题讨论】:

  • 如果现在符合您的需求,请查看我的编辑。我已经用三个 id 组对其进行了测试,应该可以按预期工作。

标签: r dplyr data-manipulation tidyverse


【解决方案1】:

我可以提供一个基本的 R 解决方案。

我们可以根据date 列逐行累加每个type 的最新值。之后我们实现每个id 组。

actualizeIDs <- function(df) sapply(
  lapply(seq_along(df[, 1]), 
         function(y) {
           d <- df[1:y, ]
           sapply(unique(d$type), 
                  function(x) {
                    d[d$type == x & d$date == max(d$date[d$type == x]), "value"]
                  }
           )
         }
  ), sum)

actualizeGroups <- function(df) {
  if (length(which(duplicated(df[, -4]))) > 0) {
    warning("Duplicated measurements, using latest row-number.")
  df <- df[- which(duplicated(df[, -4], fromLast=TRUE)), ]
  }
  df <- with(df, df[order(id, date), ])
  df$combined_value <- matrix(sapply(unique(df$id), 
                                     function(x) {
                                       actualizeIDs(df[df$id == x, ])
                                     }))
  return(df)
}

收益

> actualizeGroups(df)
   id type                date value combined_value
1   1    A 2018-07-23 06:00:00     5              5
2   1   B1 2018-07-23 06:12:00     2              7
3   1   B2 2018-07-23 06:25:00     3             10
4   1    A 2018-07-23 10:00:00     7             12
5   1   B1 2018-07-23 10:30:00     4             14
6   2    A 2018-07-23 06:00:00     3              3
7   2    A 2018-07-23 06:12:00     5              5
8   2   B2 2018-07-23 06:25:00     1              6
9   2   B3 2018-07-23 10:00:00     2              8
11  2    A 2018-07-23 10:30:00     8             11
Warning message:
In actualizeGroups(df) : Duplicated measurements, using latest row-number.

数据

df <- data.frame(id = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2),
                 type = c("A", "B1", "B2", "A", "B1", 
                          "A", "A", "B2", "B3", "A", "A"),
                 date = as.POSIXct(c("2018-07-23 6:00", "2018-07-23 6:12", 
                                     "2018-07-23 6:25", "2018-07-23 10:00", 
                                     "2018-07-23 10:30", "2018-07-23 6:00", 
                                     "2018-07-23 6:12", "2018-07-23 6:25", 
                                     "2018-07-23 10:00", "2018-07-23 10:30", 
                                     "2018-07-23 10:30")),
                 value = c(5, 2, 3, 7, 4, 3, 5, 1, 2, 7, 8))

【讨论】:

  • 谢谢,该解决方案效果很好。我没有提到我的数据集有多个组,需要为其计算当前总和。不幸的是,我无法弄清楚如何在 apply 函数系列中解释这些组
  • @tifu 如果现在适合您的需要,请查看我的编辑。我已经用三个id 组对其进行了测试,应该可以按预期工作。
  • 非常感谢,这对我帮助很大。唯一剩下的问题是,有时会同时保存两个条目,因此这些函数仍然无法在我的数据集上运行,但这我可以自己解决。
  • 可能有点太自信了。经过一些研究,当同一类型的行同时生成时,就会出现剩余的问题。在这些情况下,actualizeIDs 函数会引发错误 (invalid 'type' (list) of argument),可能是因为 max(d$date[d$type == x]) 不再导致明确的结果。我直观的解决方案是用id 分组的连续整数替换date 列,但这并没有成功。 @jaySf 我可以问一下你认为这个问题如何解决吗?
  • 是的,它有效!非常感谢您的努力,@jaySf!
猜你喜欢
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多