【问题标题】:Error applying function in grouped tibble在分组 tibble 中应用函数时出错
【发布时间】:2022-01-19 21:12:15
【问题描述】:

我正在尝试创建一个函数,该函数获取当前余额,然后每月向后计算,以根据每个月的增加和损失计算上个月末的余额。余额需要在变量组合中计算。我想要的输出看起来像这样 - month_end_balance 是我想要函数输出的。我拥有的其他一切。

type service month_starting add loss current_balance month_end_balance
A Luxury 12/1/21 2 1 20 20
A Luxury 11/1/21 4 7 NA 19
A Luxury 10/1/21 0 0 NA 22
B Economy 12/1/21 2 8 50 50
B Economy 11/1/21 4 2 NA 56
B Economy 10/1/21 0 0 NA 54

我创建了以下函数,它适用于未分组的数据。

running_balance_4 <- function(current_balance, add, loss) {
  out <- rep(NA, length(current_balance))
  out[[1]] <- current_balance[[1]]
  for (i in 2:(length(current_balance))) {
    out[[i]] <-  out[[(i-1)]] - add[[(i-1)]] + loss[[(i-1)]]
  }
  out
}

但我无法在每个组中应用它。这可能只是语法问题。

df %>%
  group_by(type, service) %>%
  arrange(type, service, desc(month_starting)) %>%
  group_modify(running_balance_4(current_balance, add, loss))

感谢任何有关语法和/或函数本身的帮助。

更新:当我尝试运行它时,我收到以下错误消息:找不到对象'current_balance'。所以我认为除了函数的任何问题之外,还可能存在语法错误。

【问题讨论】:

  • From ?group_modify, "group_modify() 适用于“数据帧输入,数据帧输出”....f 必须返回一个数据帧。" 你的函数不返回数据帧,也不适用于.x 子数据帧。您能否演示一下您的函数如何处理未分组的数据?
  • @GregorThomas 感谢您的回复。我也尝试过使用 group_map,我认为它没有这个问题。如果我只是直接运行该函数,我会得到输出,而不是所需的输出,因为平衡不会为每个变量组合重置。但是 test_function

标签: r dplyr


【解决方案1】:

我在 cmets 中看到您的功能正常工作。但是,我认为您可能希望看到使用内置 R 函数而不是应用分组函数的解决方案。

library(tibble)
library(dplyr)

df <- tribble(
  ~type,  ~service, ~month_starting,  ~add, ~loss,  ~current_balance,
  "A", "Luxury",   "12/1/21", 2,  1,  20,
  "A", "Luxury",   "11/1/21", 4,  7,  NA,
  "A", "Luxury",   "10/1/21", 0,  0,  NA,
  "B", "Economy",  "12/1/21", 2,  8,  50,
  "B", "Economy",  "11/1/21", 4,  2,  NA,
  "B", "Economy",  "10/1/21", 0,  0,  NA 
)

df %>% 
  # Two temporary columns to calculate with.
  mutate(
    # Replace current balance with 0 to work with cumulative sum.
    c_balance = coalesce(current_balance, 0),
    # Add the loss and subtract the add since we are working backwards.
    monthly = c_balance + loss - add
  ) %>%
  arrange(type, service, desc(month_starting)) %>%
  group_by(type, service) %>%
  # Taking the lag will put NA on the first element (the rows with current_balance)
  # cumsum is a built in cumulative sum
  mutate(monthly = lag(cumsum(monthly))) %>%
  ungroup() %>%
  mutate(month_end_balance = pmax(current_balance, monthly, na.rm = T))  %>%
  select(-c_balance, -monthly)

它根据current_balance 产生差异,使用cumsum 对该差异进行累积求和,然后使用lag 排列观察结果。然后可以通过current_balance 和滞后变量之间的最大值找到您所追求的输出,因为您不想要的所有值都是NA

# A tibble: 6 × 7
  type  service month_starting   add  loss current_balance month_end_balance
  <chr> <chr>   <chr>          <dbl> <dbl>           <dbl>             <dbl>
1 A     Luxury  12/1/21            2     1              20                20
2 A     Luxury  11/1/21            4     7              NA                19
3 A     Luxury  10/1/21            0     0              NA                22
4 B     Economy 12/1/21            2     8              50                50
5 B     Economy 11/1/21            4     2              NA                56
6 B     Economy 10/1/21            0     0              NA                54

【讨论】:

  • 感谢您在这里提供清晰而智能的解决方案。我应该提到你的解释也帮助解决了我不知道如何在分组表中使用我的函数的初学者问题。我以为我需要使用 'group_modify' 或 'group_map' 但不断出错 - 我仍然不完全明白为什么。但是 mutate(running_balance_4(current_balance, add, loss)) 似乎也有效。
猜你喜欢
  • 2012-12-01
  • 2020-11-08
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 2020-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多