如果满足多个条件,则具有重置选项的累积和

2024-04-04

如果满足多个条件,我正在尝试使用重置选项进行累积总和。更具体地说,我想对变量进行累积求和amount and count分组依据id如果满足这两个条件,则重新从 0 开始重置:amount>= 10 且count>= 3。我还想创建一个新列,如果满足这些条件,则包含 1,否则包含 0。

数据样本:

df <- data.frame(
    date = as.Date(c("2020-01-01", "2020-02-01", "2020-03-01", "2020-04-01", "2020-05-01", "2020-06-01", "2020-01-01", "2020-02-01", "2020-03-01", "2020-04-01", "2020-05-01", "2020-06-01", "2020-01-01", "2020-02-01", "2020-03-01", "2020-04-01", "2020-05-01", "2020-06-01")),
    id = c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C"),
    amount = c(1, 9, 5, 5, 6, 2, 10, 4, 8, 10, 6, 5, 5, 1, 6, 5, 5, 5),
    count = c(0, 2, 5, 4, 5, 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 1, 0)
)

期望的输出:

df <- data.frame(
    date = as.Date(c("2020-01-01", "2020-02-01", "2020-03-01", "2020-04-01", "2020-05-01", "2020-06-01", "2020-01-01", "2020-02-01", "2020-03-01", "2020-04-01", "2020-05-01", "2020-06-01", "2020-01-01", "2020-02-01", "2020-03-01", "2020-04-01", "2020-05-01", "2020-06-01")),
    id = c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C"),
    amount = c(1, 9, 5, 5, 6, 2, 10, 4, 8, 10, 6, 5, 5, 1, 6, 5, 5, 5),
    count = c(0, 2, 5, 4, 5, 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 1, 0),
    amount_cumsum = c(1, 10, 15, 5, 11, 2, 10, 14, 22, 32, 38, 43, 5, 6, 12, 5, 10, 5),
    count_cumsum = c(0, 2, 7, 4, 9, 1, 0, 0, 0, 0, 2, 3, 1, 2, 3, 2, 3, 0),
    condition_met = c(0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0)
)

如果可以的话,我想要一个dplyr解决方案,但也欢迎替代方案。谢谢!

更新:被作者删除的一个答案几乎解决了问题:

df %>% group_by(id) %>%
    mutate(
        amount_cumsum = purrr::accumulate(.x = amount, .f = ~ if_else(condition = .x < 10, true = .x + .y, false = .y)),
        count_cumsum = purrr::accumulate(.x = count, .f = ~ if_else(condition = .x < 3, true = .x + .y, false = .y)),
        condition_met = as.integer(amount_cumsum >= 10 & count_cumsum >= 3)
 )

或者,另一种选择:

df %>% group_by(id) %>%
    mutate(
        amount_cumsum = purrr::accumulate(.x = amount, .f = ~ case_when(.x < 10 ~ .x + .y, TRUE ~ .y)),
        count_cumsum = purrr::accumulate(.x = count, .f = ~ case_when(.x < 3 ~ .x + .y, TRUE ~ .y)),
        condition_met = as.integer(amount_cumsum >= 10 & count_cumsum >= 3)
    )

如果满足一个单个变量的条件,上面的答案将重置累积和,但不考虑是否满足其他条件。


贡献一个 base-R 解决方案:

df$amount_cumsum <- 0
df$count_cumsum <- 0    
df$condition_met <- 0  
reset = F
for (i in 1:nrow(df)) {
  if (i == 1 | reset) {
    df$amount_cumsum[i] = df$amount[i]
    df$count_cumsum[i] = df$count[i]
    reset = F
  } else if (df$id[i] != df$id[i-1]) {
    df$amount_cumsum[i] = df$amount[i]
    df$count_cumsum[i] = df$count[i]
    reset = F
  } else {
    df$amount_cumsum[i] = df$amount_cumsum[i-1] + df$amount[i]
    df$count_cumsum[i] = df$count_cumsum[i-1] + df$count[i]
  }
  
  if (df$amount_cumsum[i] >= 10 & df$count_cumsum[i] >= 3) {
    df$condition_met[i] = 1
    reset = T
  }
}

我已经扩展了您的数据集并针对此代码进行了基准测试你的解决方案 https://stackoverflow.com/questions/62817328/cumulative-sum-with-reset-option-if-multiple-conditions-are-met/62855940#62855940。 Benchmark展示了Base-R解决方案快 21 倍比 tidyverse 那个!

library(tidyverse)

dates = seq(as.Date("2019-01-01"), as.Date("2020-03-04"), by="days")

df <- data.frame(
  date = c(sample(dates, 300), sample(dates, 400), sample(dates, 350)),
  id = c(rep("A", 300), rep("B", 400), rep("C", 350)),
  amount = floor(runif(1050, 0, 15)),
  count = floor(runif(1050, 0, 5)),
  stringsAsFactors = F
)

rbenchmark::benchmark(
  "Tidy Solution" = {
    df_tidy <- df %>%
      group_by(id) %>%
      nest(data = c(amount, count)) %>%
      mutate(
        data_accumulate = purrr::accumulate(.x = data, .f = function(.x, .y) if (max(.x[1]) < 10 | max(.x[2]) < 3) .x + .y else .y)
      ) %>%
      unnest(cols = c(data_accumulate)) %>%
      rename(amount_cumsum = amount, count_cumsum = count) %>%
      unnest(cols = c(data)) %>%
      mutate(condition_met = case_when(
        amount_cumsum >= 10 & count_cumsum >= 3 ~ 1,
        TRUE ~ 0)
      )
  },
  "Base-R Solution" = {
    df_base <- df
    df_base$amount_cumsum <- 0
    df_base$count_cumsum <- 0    
    df_base$condition_met <- 0  
    reset = F  # to reset the counters
    for (i in 1:nrow(df_base)) {
      if (i == 1 | reset) {
        df_base$amount_cumsum[i] = df_base$amount[i]
        df_base$count_cumsum[i] = df_base$count[i]
        reset = F
      } else if (df_base$id[i] != df_base$id[i-1]) {
        df_base$amount_cumsum[i] = df_base$amount[i]
        df_base$count_cumsum[i] = df_base$count[i]
        reset = F
      } else {
        df_base$amount_cumsum[i] = df_base$amount_cumsum[i-1] + df_base$amount[i]
        df_base$count_cumsum[i] = df_base$count_cumsum[i-1] + df_base$count[i]
      }
      if (df_base$amount_cumsum[i] >= 10 & df_base$count_cumsum[i] >= 3) {
        df_base$condition_met[i] = 1
        reset = T
      }
    }
  },
  replications = 100)

gc()
           test replications elapsed relative user.self sys.self user.child sys.child
Base-R Solution          100    3.89    1.000      3.69      0.0         NA        NA
  Tidy Solution          100   84.00   21.594     78.65      0.2         NA        NA
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果满足多个条件,则具有重置选项的累积和 的相关文章

随机推荐

  • 将中心像素值复制到块中的多数值

    我有一个大小为 9085x10852 的图像像素预测数组 我想在每个像素周围得到一个 10x10 的块 如果中心像素值与块中的多数像素值不同 则用多数值替换中心像素值 谁能帮我吗 我正在挖掘scikit image今天寻找其他东西 如果你深
  • 视觉检漏仪未发现泄漏 VS2013

    无论我如何尝试 我似乎都无法让 VLD 捕获任何内存泄漏 有什么想法吗 这里也是输出的片段 Visual Leak Detector Version 2 4RC2 installed The thread 0x5748 has exited
  • 使用百分比而不是像素会改变 html 5 画布的属性吗?

    我正在练习 javascript 我正在尝试制作一个游戏 我希望画布元素是全屏的 因此我对高度和宽度属性使用了百分比 但是当我这样做时 它的行为与通常不同 当我运行调试代码时 它应该生成一个 50px x 50px 的盒子 但图形看起来比正
  • 错误:仅在包含所有数值变量的数据框上定义,并在大型数据集上使用 ddply

    我正在尝试按月 年 调查 ID 和网格 ID 在一个非常大的数据集 22000 条记录 上计算多个参数 例如 Er Count Mn Count 的总和和平均值 我最初尝试使用此代码来获取总和 dlply Effort All c Er C
  • Restsharp 响应中缺少 Cookie

    我将 Restsharp 用于我正在开发的 WPF 客户端 看来我在 client CookieContainer 中没有收到 cookie 在我成功向我们的服务器进行身份验证后 它始终有 0 个项目 这很奇怪 因为使用 Postman 发
  • 防止热链接 1 个特定 URL,但允许所有其他 URL

    我知道 htaccess 方法可以防止除您自己的域之外的每个站点上的热链接 但如果可能的话 我需要更高级的东西 我想允许访问我的个人服务器和所有其他站点 但仍要指出一些选定的站点并禁止它们进行热链接 我几乎想允许所有并拒绝特定的 IP 或
  • 如何减小 iPhone 应用程序的 .wav 音频文件的大小?

    我有一些循环播放的音乐 wav 文件大小约为 8 兆 我加载这个并循环它 一切都工作正常 直到我添加了另一个 4 meg wav 文件 现在游戏崩溃了 删除附加音频文件修复了崩溃问题 那么如何减小这些 wav 文件的大小呢 我想过在完成 4
  • Google Books API - 未返回图书详细信息

    所以我开始使用Google Books API对于我正在构建的应用程序 我对结果相当满意 但有时我会注意到一种奇怪的行为 即使该书存在于数据库中 某些 ISBN 也不会返回任何书籍详细信息 例如 如果我给出 https www google
  • java android eclipse 未绑定类路径变量

    Eclipse 上的 Unbound Class Path 变量是什么意思 我收到错误 但不知道如何修复它 Eclipse 中 Unbound Classpath 变量的含义是什么 这是一条警告消息 内容是 类路径变量 http help
  • Android:我可以从第 3 方应用程序使用此意图吗?

    我正在使用意图通过 Twitter 客户端发布消息 当手机上没有 Twitter 应用程序时 我想将用户重定向到市场 但异常 ActivityNotFoundException 不起作用 每次 当我没有 Twitter 应用程序时 我都会收
  • 程序中出现奇怪的错误“Ora-01001无效光标”

    昨天我处理了生产过程中的一个奇怪的错误 语句执行失败 if v cursor isopen then close v cursor here was an error end if 经过一番研究后 我发现问题出在打开该游标的子程序中 我通过
  • React 显示 0,而不是使用短路 (&&) 条件组件显示任何内容

    我有以下简单的短路语句 应该显示一个组件或不显示任何内容 profileTypesLoading
  • 条件变量可能未初始化

    我正在编写一个程序 根据 CLI 标志将传入文件子集为一个或两个输出文件 至少它的工作原理如下 use std fs File io Write fn main Would be a CLI flag let write all true
  • 瑞典语字符和 UTF-8

    我在所有页面上都使用 UTF 8 但一些瑞典语字符 和 变得混乱 只是一个带有一些字母的方框 我的数据库设置为 utf8 general ci 但我什至没有连接 所以这并不重要 或者我应该使用另一个字符集 这不是瑞典语网站 都是英文的 但我
  • 如何在 Linux 中创建别名? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 假设我想为 srm 创建一个别名 安全删除 这样每次使用 srm 时 都会运行交互式 rm 命令 例如rm i 需要对必要的配置文件进行此
  • 如果标签有重音,NSXMLParser 不会获取所有标签

    我有一个对数据库进行不同更改的网络服务 当我使用带有 sql 标签的 Web 服务返回行时 如下所示
  • Push 替换数组中的旧值

    也许是因为我工作了一整天 我看不到问题所在 但在下面的代码中 警报仅显示最后添加的值 并且不会将值推送到数组中 window sortControl sortControlPanel div sortControl simpleSortCr
  • 为什么 DbSet.Add 工作这么慢?

    8 个月前曾在这里讨论过同样的话题 如何加快 DbSet Add 的速度 https stackoverflow com questions 4355474 how do i speed up dbset add 除了使用 SqlBulkC
  • JavaFX 字体渲染中的错误字符间距(字距调整)(在 Linux 中)

    我已经开始在 JavaFX 中开发一个应用程序 并且遇到了一个问题 我可以找到很少的有用信息 Linux 中字符之间的间距非常不均匀 我不是在谈论不同字符的宽度 而是在谈论字符之间的空格 它在普通文本中可见 但以下示例比普通文本更好地说明了
  • 如果满足多个条件,则具有重置选项的累积和

    如果满足多个条件 我正在尝试使用重置选项进行累积总和 更具体地说 我想对变量进行累积求和amount and count分组依据id如果满足这两个条件 则重新从 0 开始重置 amount gt 10 且count gt 3 我还想创建一个