不断求和 R 中的列直到满足条件

时间:2021-04-13 12:49:24

标签: r for-loop if-statement lag cumsum

我正在尽我最大的努力学习 R,这是我在这个论坛上的第一篇文章。

我目前有一个数据框,其中包含一个填充向量“x”和一个未填充向量“counter”,如下所示:

x <- c(NA,1,0,0,0,0,1,1,1,1,0,1)

df <- data.frame("x" = x, "counter" = 0)

    x counter
1  NA       0
2   1       0
3   0       0
4   0       0
5   0       0
6   0       0
7   1       0
8   1       0
9   1       0
10  1       0
11  0       0
12  1       0

我在尝试编写代码时遇到了令人惊讶的困难,该代码将简单地填充计数器,以便计数器对 x 中的累积连续 1 求和,但当 x 为零时又恢复为零。因此,我希望计数器按照上述示例进行如下计算:

    x counter
1  NA       NA
2   1       1
3   0       0
4   0       0
5   0       0
6   0       0
7   1       1
8   1       2
9   1       3
10  1       4
11  0       0
12  1       1

我尝试过使用 lag() 和 ifelse(),无论是否有 for 循环,但似乎离可行的解决方案越来越远(虽然滞后让我接近,但数字没有按预期计算。 ...我的 ifelse 和 for 循环最终以长度为 1 的 NA_real_、NA 或 1 向量结束。我也考虑过 cumsum - 但不确定如何将范围限定为 1s - 并搜索并查看了类似的帖子,例如 How to add value to previous row if condition is met;但是,我仍然无法弄清楚我期望什么是一项非常简单的任务。

诚然,我正处于早期 R 学习曲线的低谷,非常感谢社区中的任何人可以提供的任何帮助和建设性反馈。谢谢。

2 个答案:

答案 0 :(得分:1)

您可以使用:

library(dplyr)

df %>%
  group_by(x1 = cumsum(replace(x, is.na(x), 0) == 0)) %>%
  mutate(counter = (row_number() - 1) * x) %>%
  ungroup %>%
  select(-x1)

#       x counter
#   <dbl>   <dbl>
# 1    NA      NA
# 2     1       1
# 3     0       0
# 4     0       0
# 5     0       0
# 6     0       0
# 7     1       1
# 8     1       2
# 9     1       3
#10     1       4
#11     0       0
#12     1       1

解释步骤 -

  • 创建一个新列 (x1),将 NA 中的 x 替换为 0 并将组值增加 1(使用 cumsum)每当 x = 0 .
  • 对于每组,用 0 减去行号,然后乘以 x。这种乘法是必要的,因为它有助于保持 counter 为 0,其中 x = 0counterNA,其中 xNA

答案 1 :(得分:1)

欢迎@cpanagakos。

dplyr::lag 中,不可能使用仍然不存在的列。 (它不能指代自己。) https://www.reddit.com/r/rstats/comments/a34n6b/dplyr_use_previous_row_from_a_column_thats_being/

例如:

library(tidyverse)


df <- tibble("x" = c(NA, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1))

# error: lag cannot refer to a column that still doesn't exist
df %>%
  mutate(counter = case_when(is.na(x) ~ coalesce(lag(counter), 0),
                             x == 0   ~ 0,
                             x == 1   ~ lag(counter) + 1))
#> Error: Problem with `mutate()` input `counter`.
#> x object 'counter' not found
#> i Input `counter` is `case_when(...)`.

因此,如果您有一个“重置”计数器的标准,则需要编写一个公式,在您需要重置时更改组,然后引用 row_number,它将在组内的 1 处重新启动(就像@Ronald Shah 和其他人建议的那样):

Create sequential counter that restarts on a condition within panel data groups

df %>%
  group_by(x1 = cumsum(!coalesce(x, 0))) %>%
  mutate(counter = row_number() - 1) %>%
  ungroup()
#> # A tibble: 12 x 3
#>        x    x1 counter
#>    <dbl> <int>   <dbl>
#>  1    NA     1      NA
#>  2     1     1       1
#>  3     0     2       0
#>  4     0     3       0
#>  5     0     4       0
#>  6     0     5       0
#>  7     1     5       1
#>  8     1     5       2
#>  9     1     5       3
#> 10     1     5       4
#> 11     0     6       0
#> 12     1     6       1

这将是在 R 中使用 for 循环的少数情况之一:因为替代方案在概念上更难以理解。