【问题标题】:Purrr's Modify-In FunctionPurrr 的修改功能
【发布时间】:2026-01-10 12:40:01
【问题描述】:

我正在尝试使用 purrr 的 modify_in 来修改列表的元素。列表示例:

tib_list <- map(1:3, ~ tibble(col_one = runif(5),
    col_two = runif(5), col_three = runif(5)))

假设我想将列表的元素 2 和 3 更改为取消选择 col_one。我想这样做:

modify_in(tib_list, 2:length(tib_list), ~ select(.x, -col_one) 

但这会产生错误。然后我想做这样的事情,但这最终会重复列表

map(1:3, ~ modify_in(tib_list, .x, ~ select(.x, -col_one)) 

【问题讨论】:

    标签: r tidyverse purrr


    【解决方案1】:

    我认为您想使用modify_at,它可以让您指定元素名称或位置。 modify_in 允许我们只使用一个位置,例如 purrr::pluck

    library(tidyverse)
    
    tib_list <- map(1:3, ~ tibble(col_one = runif(5), col_two = runif(5), col_three = runif(5)))
    
    modify_at(tib_list, c(2,3), ~ select(.x, -col_one))
    #> [[1]]
    #> # A tibble: 5 x 3
    #>   col_one col_two col_three
    #>     <dbl>   <dbl>     <dbl>
    #> 1   0.190   0.599     0.824
    #> 2   0.214   0.172     0.106
    #> 3   0.236   0.666     0.584
    #> 4   0.373   0.903     0.252
    #> 5   0.875   0.196     0.643
    #> 
    #> [[2]]
    #> # A tibble: 5 x 2
    #>   col_two col_three
    #>     <dbl>     <dbl>
    #> 1   0.513     0.113
    #> 2   0.893     0.377
    #> 3   0.275     0.675
    #> 4   0.529     0.612
    #> 5   0.745     0.405
    #> 
    #> [[3]]
    #> # A tibble: 5 x 2
    #>   col_two col_three
    #>     <dbl>     <dbl>
    #> 1   0.470     0.789
    #> 2   0.181     0.289
    #> 3   0.680     0.213
    #> 4   0.772     0.114
    #> 5   0.314     0.895
    

    reprex package (v0.3.0) 于 2021 年 8 月 27 日创建

    我们可以将modify_in 用于一个位置,但提供诸如c(2,3) 之类的向量意味着我们要访问嵌套列表中第二个父元素的第三个元素。这就是我们看到以下错误的原因。

    # works
    modify_in(tib_list, 2, ~ select(.x, -col_one))
    
    #> [[1]]
    #> # A tibble: 5 x 3
    #>   col_one col_two col_three
    #>     <dbl>   <dbl>     <dbl>
    #> 1   0.109  0.697     0.0343
    #> 2   0.304  0.645     0.851 
    #> 3   0.530  0.786     0.600 
    #> 4   0.708  0.0324    0.605 
    #> 5   0.898  0.232     0.567 
    #> 
    #> [[2]]
    #> # A tibble: 5 x 2
    #>   col_two col_three
    #>     <dbl>     <dbl>
    #> 1  0.766     0.157 
    #> 2  0.0569    0.0422
    #> 3  0.943     0.0850
    #> 4  0.947     0.0806
    #> 5  0.761     0.297 
    #> 
    #> [[3]]
    #> # A tibble: 5 x 3
    #>   col_one col_two col_three
    #>     <dbl>   <dbl>     <dbl>
    #> 1   0.878   0.864     0.540
    #> 2   0.168   0.745     0.120
    #> 3   0.943   0.338     0.535
    #> 4   0.353   0.478     0.204
    #> 5   0.267   0.669     0.478
    
    # doesn't work
    modify_in(tib_list, c(2,3), ~ select(.x, -col_one))
    
    #> Error in UseMethod("select"): no applicable method for 'select' applied to an object of class "c('double', 'numeric')"
    

    【讨论】:

      【解决方案2】:

      我从未使用过modify_in,但你可以使用

      library(purrr)
      library(dplyr)
      
      tib_list %>% 
        imap(~ if (.y > 1) { select(.x, -col_one) } else { .x })
      

      得到

      [[1]]
      # A tibble: 5 x 3
        col_one col_two col_three
          <dbl>   <dbl>     <dbl>
      1   0.710   0.189    0.644 
      2   0.217   0.946    0.955 
      3   0.590   0.770    0.0180
      4   0.135   0.101    0.888 
      5   0.640   0.645    0.346 
      
      [[2]]
      # A tibble: 5 x 2
        col_two col_three
          <dbl>     <dbl>
      1   0.267    0.926 
      2   0.456    0.0902
      3   0.659    0.707 
      4   0.421    0.0451
      5   0.801    0.220 
      
      [[3]]
      # A tibble: 5 x 2
        col_two col_three
          <dbl>     <dbl>
      1   0.437     0.649
      2   0.256     0.466
      3   0.331     0.594
      4   0.586     0.558
      5   0.625     0.444
      

      【讨论】:

      • 这是一个非常有趣的方法。感谢您发布它 - 很高兴看到 imap 如何与这样的东西一起使用。
      【解决方案3】:

      我们可以使用modify_if

      modify_if(tib_list,.f =  ~ .x %>% select(-col_one), 
             .p = seq_along(tib_list) != 1)
      

      -输出

      [[1]]
      # A tibble: 5 x 3
        col_one col_two col_three
          <dbl>   <dbl>     <dbl>
      1   0.819   0.666    0.384 
      2   0.183   0.549    0.0211
      3   0.374   0.240    0.252 
      4   0.359   0.913    0.792 
      5   0.515   0.402    0.217 
      
      [[2]]
      # A tibble: 5 x 2
        col_two col_three
          <dbl>     <dbl>
      1   0.696    0.0269
      2   0.433    0.147 
      3   0.235    0.743 
      4   0.589    0.748 
      5   0.635    0.851 
      
      [[3]]
      # A tibble: 5 x 2
        col_two col_three
          <dbl>     <dbl>
      1  0.707      0.976
      2  0.0966     0.130
      3  0.574      0.572
      4  0.854      0.680
      5  0.819      0.582
      

      【讨论】: