【问题标题】:Using dplyr rewrite a loop that shifts a value in a vector使用 dplyr 重写一个在向量中移动一个值的循环
【发布时间】:2022-01-09 02:42:07
【问题描述】:

这是基本 R 中的简单循环:

# prep
x <- sort(round(10 * rnorm(10)))
res.sd <- NULL
res.var <- NULL
res.mad <- NULL
#loop
for(i in -20:20){
 x[10] <- i
 res.sd <- c(res.sd, sd(x))
 res.var <- c(res.var, var(x))
 res.mad <- c(res.mad, mad(x))
}

我想在 dplyr 中重写这个

【问题讨论】:

  • dplyr 通常用于数据帧。您的意思是仅使用基于非循环的方法来解决您的问题吗?
  • 也许 map/apply 函数更适合这种情况。
  • @ekoam:是的。我也同意:这个问题本来可以更好地表述。

标签: r for-loop dplyr


【解决方案1】:

我们可以使用 purrr 和 tibble 的组合。

library(tidyverse)

set.seed(0)

x <- sort(round(10 * rnorm(10)))

map_dfr(-20:20, ~ tibble(
  res.sd = sd(c(x[-10], .)),
  res.var = var(c(x[-10], .)),
  res.mad = mad(c(x[-10], .))
))
#> # A tibble: 41 × 3
#>    res.sd res.var res.mad
#>     <dbl>   <dbl>   <dbl>
#>  1   11.7    138.    15.6
#>  2   11.6    134.    15.6
#>  3   11.4    130.    15.6
#>  4   11.2    126.    15.6
#>  5   11.1    122.    15.6
#>  6   10.9    119.    15.6
#>  7   10.8    116.    14.8
#>  8   10.6    113.    14.1
#>  9   10.5    110.    13.3
#> 10   10.4    108.    12.6
#> # … with 31 more rows

由reprex package (v2.0.1) 于 2022-01-09 创建

【讨论】:

    【解决方案2】:

    如果我正确理解您的代码,它会执行以下操作:

    1. 生成 10 个随机数,存储在 x 中。
    2. 在迭代-20:20 的循环中,将x 的第10 个值替换为迭代值。
    3. 计算修改后向量的 SD、方差和中值绝对偏差,并存储这些计算结果。

    正如 ekoam 指出的那样,这种类型的操作不适合 dplyr 的预期目的。也就是说,存储列表列的能力使这成为可能(尽管效率低下,因为它需要存储x 向量的多个副本)。如果您在第一行之前添加set.seed(0) 以控制随机化,则以下代码将产生与您的代码相同的结果。

    set.seed(0)
    df <- tibble(
      x = list(sort(round(10 * rnorm(10)))),
      y = -20:20
    ) %>% 
      rowwise() %>% 
      mutate(
        res.sd = sd(c(x[-10], y)),
        res.var = var(c(x[-10], y)),
        res.mad = mad(c(x[-10], y))
      )
    
    # A tibble: 41 × 5
    # Rowwise: 
       x              y res.sd res.var res.mad
       <list>     <int>  <dbl>   <dbl>   <dbl>
     1 <dbl [10]>   -20   11.7    138.    15.6
     2 <dbl [10]>   -19   11.6    134.    15.6
     3 <dbl [10]>   -18   11.4    130.    15.6
     4 <dbl [10]>   -17   11.2    126.    15.6
     5 <dbl [10]>   -16   11.1    122.    15.6
     6 <dbl [10]>   -15   10.9    119.    15.6
     7 <dbl [10]>   -14   10.8    116.    14.8
     8 <dbl [10]>   -13   10.6    113.    14.1
     9 <dbl [10]>   -12   10.5    110.    13.3
    10 <dbl [10]>   -11   10.4    108.    12.6
    

    或者,我们可以对lapply 和sapply 进行一些巧妙处理,然后将结果存储在一个小标题中。注意这里几乎没有重复代码:

    set.seed(0)
    x <- sort(round(10 * rnorm(10)))
    y <- -20:20
    lapply(list(sd = sd, var = var, mad = mad), function(func) {
      
      sapply(y, function(j) {
        func(c(x[-10], j))
      }) 
    }) %>% 
      as_tibble()
    
    # A tibble: 41 × 3
          sd   var   mad
       <dbl> <dbl> <dbl>
     1  11.7  138.  15.6
     2  11.6  134.  15.6
     3  11.4  130.  15.6
     4  11.2  126.  15.6
     5  11.1  122.  15.6
     6  10.9  119.  15.6
     7  10.8  116.  14.8
     8  10.6  113.  14.1
     9  10.5  110.  13.3
    10  10.4  108.  12.6
    # … with 31 more rows
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-05
      • 2021-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-21
      • 1970-01-01
      相关资源
      最近更新 更多