如何在没有循环的情况下迭代地迭代列的值?

发布于 2025-01-27 06:38:23 字数 1499 浏览 1 评论 0原文

我想迭代地更改列的值(示例中的值2)。 value2在时间上由value1和更新的value2在时间i和i-1中。

时间值按上升顺序库存。

对组柱的每个值分开进行处理。

但是如在我的示例中所述,我无法成功使用accompulate2(purrr软件包)更新value2。

也许有人可以给我一些建议。

谢谢。

input <- data.frame(group=c(1,1,1,2,2,2,2),
                time=c(1,2,3,1,2,3,4),
                value1=c(4,2,2,3,3,3,3),
                value2=c(4,2,1,3,3,1,1))

input<-arrange(input, group,time)

my_function <- function(df) {
df %>%
as_tibble() %>%
group_by(group) %>%
mutate(value2=purrr::accumulate2(.x = value2, .y = ((value1==lag(value1))
                                              & (lag(value2)==value1)
                                              & (value1!=value2))[-1],
                               .f = function(.i_1, .i, .y) {
                                 if (.y) {.i_1} else {.i}  
                               }) %>% unlist())
}

> input
  group time value1 value2
1     1    1      4      4
2     1    2      2      2
3     1    3      2      1
4     2    1      3      3
5     2    2      3      3
6     2    3      3      1
7     2    4      3      1

output <- my_function(input)

> output
  group time value1 value2
1     1     1      4      4
2     1     2      2      2
3     1     3      2      2 -> data change (OK)
4     2     1      3      3
5     2     2      3      3
6     2     3      3      3 -> data change (OK)
7     2     4      3      1 -> no data change / should be replaced by 3

I would like to change iteratively the values of a column (value2 in the example). value2 at time i is conditioned by value1 and updated value2 at time i and i-1.

Time values are stocked in ascending order.

Treatment is done separetely for each value of the group colum.

But as describe on my example, I can't succeed to update value2 with accumulate2 (purrr package).

Maybe someone could give me some advices to do this.

Thank you.

input <- data.frame(group=c(1,1,1,2,2,2,2),
                time=c(1,2,3,1,2,3,4),
                value1=c(4,2,2,3,3,3,3),
                value2=c(4,2,1,3,3,1,1))

input<-arrange(input, group,time)

my_function <- function(df) {
df %>%
as_tibble() %>%
group_by(group) %>%
mutate(value2=purrr::accumulate2(.x = value2, .y = ((value1==lag(value1))
                                              & (lag(value2)==value1)
                                              & (value1!=value2))[-1],
                               .f = function(.i_1, .i, .y) {
                                 if (.y) {.i_1} else {.i}  
                               }) %>% unlist())
}

> input
  group time value1 value2
1     1    1      4      4
2     1    2      2      2
3     1    3      2      1
4     2    1      3      3
5     2    2      3      3
6     2    3      3      1
7     2    4      3      1

output <- my_function(input)

> output
  group time value1 value2
1     1     1      4      4
2     1     2      2      2
3     1     3      2      2 -> data change (OK)
4     2     1      3      3
5     2     2      3      3
6     2     3      3      3 -> data change (OK)
7     2     4      3      1 -> no data change / should be replaced by 3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别低头,皇冠会掉 2025-02-03 06:38:23

看来您的问题在于您的算法。不幸的是,由于您没有在这里解释,因此我们无法为您提供帮助。

purrr :: comguate2很难使用,因此我建议您尽可能地分配代码。这将使您的代码更具可读性,并使调试和发现错误更加容易。

例如,请考虑以下内容:

library(tidyverse)
input <- data.frame(group=c(1,1,1,2,2,2,2),
                    time=c(1,2,3,1,2,3,4),
                    value1=c(4,2,2,3,3,3,3),
                    value2=c(4,2,1,3,3,1,1))
input <- arrange(input, group,time)

#document your functions when it
#' @param .i_1 this is ...
#' @param .i this is ...
#' @param .y this is ...
my_accu_function = function(.i_1, .i, .y) {
    if(.y) {.i_1} else {.i}  
}

my_function <- function(df) {
    df %>%
        as_tibble() %>%
        group_by(group) %>%
        mutate(
            cond = value1==lag(value1) & 
              lag(value2)==value1 & 
              value1!=value2,
            value2_update=purrr::accumulate2(.x = value2, 
                                             .y = cond[-1],
                                             .f = my_accu_function) %>% unlist()
        )
}


input
#>   group time value1 value2
#> 1     1    1      4      4
#> 2     1    2      2      2
#> 3     1    3      2      1
#> 4     2    1      3      3
#> 5     2    2      3      3
#> 6     2    3      3      1
#> 7     2    4      3      1
output = my_function(input)
output
#> # A tibble: 7 x 6
#> # Groups:   group [2]
#>   group  time value1 value2 cond  value2_update
#>   <dbl> <dbl>  <dbl>  <dbl> <lgl>         <dbl>
#> 1     1     1      4      4 FALSE             4
#> 2     1     2      2      2 FALSE             2
#> 3     1     3      2      1 TRUE              2
#> 4     2     1      3      3 FALSE             3
#> 5     2     2      3      3 FALSE             3
#> 6     2     3      3      1 TRUE              3
#> 7     2     4      3      1 FALSE             1
stopifnot(output$value2_update[7]==3)
#> Error: output$value2_update[7] == 3 is not TRUE

在2022-05-11创建的 reprex package (v2.0.1.1) )

您可以看到cond最终是错误的,因此accamulate2做出了当前值1而不是上一个值3

如果您向我们解释您的算法,也许我们可以帮助您设置正确的条件cond,以便获得正确的输出。

It seems that your problem lies in your algorithm. Unfortunately, as you didn't explain it here, we cannot help you in that matter.

purrr::accumulate2 can be hard to use, so I advise you to split your code as much as possible. This will make your code much more readable, and will make debugging and finding errors much easier.

For instance, consider this:

library(tidyverse)
input <- data.frame(group=c(1,1,1,2,2,2,2),
                    time=c(1,2,3,1,2,3,4),
                    value1=c(4,2,2,3,3,3,3),
                    value2=c(4,2,1,3,3,1,1))
input <- arrange(input, group,time)

#document your functions when it
#' @param .i_1 this is ...
#' @param .i this is ...
#' @param .y this is ...
my_accu_function = function(.i_1, .i, .y) {
    if(.y) {.i_1} else {.i}  
}

my_function <- function(df) {
    df %>%
        as_tibble() %>%
        group_by(group) %>%
        mutate(
            cond = value1==lag(value1) & 
              lag(value2)==value1 & 
              value1!=value2,
            value2_update=purrr::accumulate2(.x = value2, 
                                             .y = cond[-1],
                                             .f = my_accu_function) %>% unlist()
        )
}


input
#>   group time value1 value2
#> 1     1    1      4      4
#> 2     1    2      2      2
#> 3     1    3      2      1
#> 4     2    1      3      3
#> 5     2    2      3      3
#> 6     2    3      3      1
#> 7     2    4      3      1
output = my_function(input)
output
#> # A tibble: 7 x 6
#> # Groups:   group [2]
#>   group  time value1 value2 cond  value2_update
#>   <dbl> <dbl>  <dbl>  <dbl> <lgl>         <dbl>
#> 1     1     1      4      4 FALSE             4
#> 2     1     2      2      2 FALSE             2
#> 3     1     3      2      1 TRUE              2
#> 4     2     1      3      3 FALSE             3
#> 5     2     2      3      3 FALSE             3
#> 6     2     3      3      1 TRUE              3
#> 7     2     4      3      1 FALSE             1
stopifnot(output$value2_update[7]==3)
#> Error: output$value2_update[7] == 3 is not TRUE

Created on 2022-05-11 by the reprex package (v2.0.1)

You can see that cond is FALSE in the end, so accumulate2 did its job putting the current value 1 and not the previous value 3.

If you explain your algorithm to us, maybe we can help you with setting the proper condition cond so that you get the right output.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文