【问题标题】:R purrr how to rename column of nested dfR purrr如何重命名嵌套df的列
【发布时间】:2021-12-20 16:30:57
【问题描述】:

我有一个数据框列表,每个数据框都有两列,分别名为“place”和“data”。 “place”是一个字符,“data”是一个嵌套数据框,其中包含一个名为“value”的数字列。

对于列表中的每个数据框,我想将嵌套数据框的“值”列重命名为“位置”列的值。

library(tidyverse)
some_dt = tibble(place = c("a","a", "b","b","c","c"), 
                 value = c(1,2,1,4,5,6))

# here is a list of data frames...
ls_df <- 
  some_dt %>% 
  group_by(place) %>% 
  nest() %>% 
  split(.$place)

我试过了:

map2(ls_df$data, 
     ls_df$place,
     ~rename(.x, .y = "value"))

或:

map2(ls_df$data, 
     ls_df$place,
     ~rename_with(.x, ~ .y, "value"))

但我得到一个空列表。

如何使用外部数据框列的内容重命名“值”列?

【问题讨论】:

    标签: r purrr data-wrangling


    【解决方案1】:

    我们可以使用map 循环遍历list ('ls_df'),提取'place' 列,然后rename 使用'place' 值提取提取的'data' 列

    library(dplyr)
    library(purrr)
    ls_df2 <- map(ls_df, ~ {
         nm <- .x$place
        .x$data[[1]] <- .x$data[[1]] %>%
          rename_with(~ nm, "value")
       .x
    })
    

    -检查

    > map(ls_df2, ~ .x$data)
    $a
    $a[[1]]
    # A tibble: 2 × 1
          a
      <dbl>
    1     1
    2     2
    
    
    $b
    $b[[1]]
    # A tibble: 2 × 1
          b
      <dbl>
    1     1
    2     4
    
    
    $c
    $c[[1]]
    # A tibble: 2 × 1
          c
      <dbl>
    1     5
    2     6
    

    请注意,当我们splitting 数据时,它会返回一个list。因此,我们不能直接访问“数据”列,即

    > ls_df$data
    NULL
    > ls_df$place
    NULL
    

    或者另一种选择是

    some_dt %>%
      nest_by(place) %>%
      mutate(data = data %>% 
              rename_with(~ place, value) %>%
              list(.)) %>% 
      ungroup
    # A tibble: 3 × 2
      place data            
      <chr> <list>          
    1 a     <tibble [2 × 1]>
    2 b     <tibble [2 × 1]>
    3 c     <tibble [2 × 1]>
    

    【讨论】:

    • 谢谢,非常有教益。这对我帮助很大!
    【解决方案2】:

    您还可以遍历每个列表元素,然后使用 mutate 来重命名嵌套数据框。

    ls_df %>% 
      modify(~ mutate(.x,
                      data = map(data,
                                 ~ set_names(.x, first(place)))))
    

    在这种情况下,您实际上可以进一步简化。

    ls_df %>% 
      modify(~ mutate(.x,
                      data = map2(data, place, set_names)))
    
    # which can collapse down to as simple as this
    ls_df %>% 
      modify(mutate, data = map2(data, place, set_names))
    

    通过这种方法,您实际上可以考虑是否真的需要该列表。嵌套的 tibble 可能更容易直接使用。

    ls_df %>% 
      bind_rows() %>% 
      mutate(data = map2(data, place, set_names))
    

    【讨论】:

      【解决方案3】:

      你也可以试试这样的:

      library(tidyverse)
      
      map(ls_df,
          ~ map2(.x$place, 
                 .x$data,
                 ~rename(.y, 
                         !!sym(.x) := value)
                 )
          )
      #> $a
      #> $a[[1]]
      #> # A tibble: 2 x 1
      #>       a
      #>   <dbl>
      #> 1     1
      #> 2     2
      #> 
      #> 
      #> $b
      #> $b[[1]]
      #> # A tibble: 2 x 1
      #>       b
      #>   <dbl>
      #> 1     1
      #> 2     4
      #> 
      #> 
      #> $c
      #> $c[[1]]
      #> # A tibble: 2 x 1
      #>       c
      #>   <dbl>
      #> 1     5
      #> 2     6
      

      【讨论】:

        【解决方案4】:

        您可以创建一个使用基本colnames() 重命名的函数,然后将其映射到所有列表元素,如下所示:

        # The fn:
        rnm <- function(x) {
          colnames(x$data[[1]]) <- x$place
          x
        }
        
        # Result:
        res <- ls_df |> purrr::map(.f = rnm)
        
        # Check if it's the desired output:
        res$a$data
        
        # [[1]]
        #  A tibble: 2 × 1
        #      a
        #   <dbl>
        # 1     1
        # 2     2
        
        

        【讨论】:

          猜你喜欢
          • 2022-11-17
          • 2020-10-06
          • 1970-01-01
          • 2019-06-25
          • 2020-12-06
          • 2016-06-04
          • 2021-10-30
          • 2022-01-02
          • 1970-01-01
          相关资源
          最近更新 更多