我们可以使用 purrr::map() 来 *in-place* 修改嵌套结构中的字符串吗?

Can we use purrr::map() to *in-place* modify strings in nested structures?

我有一个嵌套命名列表的 tibble。我想在命名列表上应用清理函数(例如 janitor::make_clean_names()):名称 和值 。根据我对 purrr 包的基本理解,我认为 map() 适合这样的任务。

但是,我不知道如何执行这样的清理in-place,类似于dplyr的[=20=的功能].

例子

这里有一个小标题:

library(tibble)

my_tibble <-
  tibble(
  name = c("economics", "history","psychology", "biology"),
  info = list(
    list(
      GDP = "Gross domestic product",
      GNI = "Gross national income"
    ),
    NULL,
    list(
      Gestalt = "theory of perception",
      `Affective neuroscience` = "Study of the neural mechanisms of emotion",
      `Personality` = "personality and its variation among individuals"
    ),
    list(Photosynthesis = "convert light energy into chemical energy")
  )
)

my_tibble
#> # A tibble: 4 x 2
#>   name       info            
#>   <chr>      <list>          
#> 1 economics  <named list [2]>
#> 2 history    <NULL>          
#> 3 psychology <named list [3]>
#> 4 biology    <named list [1]>

reprex package (v0.3.0)

于 2021-02-04 创建

当我们查看 info list-column 时,我们看到它嵌套了 4 个列表(一个为空),这些列表是 named

library(dplyr)

pull(my_tibble, info)

## [[1]]
## [[1]]$GDP
## [1] "Gross domestic product"

## [[1]]$GNI
## [1] "Gross national income"


## [[2]]
## NULL

## [[3]]
## [[3]]$Gestalt
## [1] "theory of perception"

## [[3]]$`Affective neuroscience`
## [1] "Study of the neural mechanisms of emotion"

## [[3]]$Personality
## [1] "personality and its variation among individuals"


## [[4]]
## [[4]]$Photosynthesis
## [1] "convert light energy into chemical energy"

我想做一个简单的文本 clean-up,janitor::make_clean_names() 很适合这个任务。我如何将 make_clean_names() 应用到 info 和 return 下列表中的名称和值相同的 my_tibble (但现在使用干净的字符串)?

期望输出

my_tibble_cleaned <-
  tibble(
  name = c("economics", "history","psychology", "biology"),
  info = list(
    list(
      gdp = "gross_domestic_product",
      gdp = "gross_national_income"
    ),
    NULL,
    list(
      gestalt = "theory_of_perception",
      affective_neuroscience = "study_of_the_neural_mechanisms_of_emotion",
      personality = "personality_and_its_variation_among_individuals"
    ),
    list(photosynthesis = "convert_light_energy_into_chemical_energy")
  )
)

所需方法
在数据框的平行宇宙中,我会做这样的事情:

my_df <-
  data.frame(name = c("economics", "psychology", "biology"),
             info = c("GDP", "Affective neuroscience", "Photosynthesis"))

my_df %>%
  mutate(across(info, janitor::make_clean_names))

dplyr 代码只是为了展示我正在寻找的简单性。我们可以为 in-place 修改嵌套在 tibble 中的结构提供如此简洁的代码吗?我想 purrr::map() 应该很方便,但我不知道怎么做。

您可以单独清理名称和值并将它们组合在一起。

library(janitor)
library(dplyr)
library(purrr)

result <- my_tibble %>%
            mutate(info = map(info, ~setNames(map(.x, make_clean_names), 
                                             make_clean_names(names(.x)))))

这个returns输出为:

result$info

#[[1]]
#[[1]]$gdp
#[1] "gross_domestic_product"

#[[1]]$gni
#[1] "gross_national_income"


#[[2]]
#named list()

#[[3]]
#[[3]]$gestalt
#[1] "theory_of_perception"

#[[3]]$affective_neuroscience
#[1] "study_of_the_neural_mechanisms_of_emotion"

#[[3]]$personality
#[1] "personality_and_its_variation_among_individuals"


#[[4]]
#[[4]]$photosynthesis
#[1] "convert_light_energy_into_chemical_energy"

我们可以使用

library(dplyr)
library(purrr)
library(janitor)
my_tibble %>%
           mutate(info = map(info, ~set_names(map(.x, make_clean_names), 
                                         make_clean_names(names(.x)))))