如何在不重新分配的情况下修改嵌套在列表中的数据框
How to modify a dataframe nested inside a list without re-assignment
我有一个包含多个元素的列表对象。一个元素是我希望修改的数据框:我想执行一些操作,例如列重命名和改变新列。
虽然一种简单的方法是提取嵌套数据框,修改它,最后将输出重新分配给原始父列表,但我想避免这种解决方案,因为它需要中间分配。
例子
数据。让我们构建一个包含多个数据对象的列表
library(tibble)
my_list <- lst(letters, mtcars, co2, uspop, iris)
任务。
我想修改my_list$mtcars
为:
- 重命名
cyl
列
- 计算一个新列,对
mpg
列中的值求平方根
我想修改my_list$iris
为:
- select 以
sepal
开头的列
- 将它们重命名为小写
最终我希望得到一个与原始 my_list
相同的列表对象,除了我对 mtcars
和 iris
.[=23= 所做的更改之外]
我的尝试。现在,我知道实现此目的的唯一方法涉及重新分配:
library(dplyr)
my_list$mtcars <-
my_list$mtcars %>%
rename("Number of cylinders" = cyl) %>%
mutate(sqrt_of_mpg = sqrt(mpg))
my_list$iris <-
my_list$iris %>%
select(starts_with("Sepal")) %>%
rename_with(tolower)
我的问题: 给定 my_list
,我如何通过名称指向嵌套元素,指定应该发生哪些操作来修改它,并取回parent my_list
只做了那些修改?
我想象某种管道看起来像这样(只是为了了解我的大致想法)
## DEMO ##
my_list %>%
update_element(which = "mtcars", what = rename, mutate) %>%
update_element(which = "iris", what = select, rename)
谢谢!
你可以试试purrr
的modify_at
功能
library(tidyverse)
my_list %>%
modify_at("mtcars", ~rename(.,"Number of cylinders" = cyl) %>%
mutate(sqrt_of_mpg = sqrt(mpg))) %>%
modify_at("iris", ~select(., starts_with("Sepal")) %>%
rename_with(tolower))
您可以使用 imap
为每次迭代传递名称和数据,但这并不接近您的总体想法。
library(dplyr)
my_list <- purrr::imap(my_list, ~{
if(.y == 'mtcars')
.x %>% rename("Number of cylinders" = cyl) %>%mutate(sqrt_of_mpg = sqrt(mpg))
else if(.y == 'iris')
.x %>% select(starts_with("Sepal")) %>% rename_with(tolower)
else .x
})
我有一个包含多个元素的列表对象。一个元素是我希望修改的数据框:我想执行一些操作,例如列重命名和改变新列。
虽然一种简单的方法是提取嵌套数据框,修改它,最后将输出重新分配给原始父列表,但我想避免这种解决方案,因为它需要中间分配。
例子
数据。让我们构建一个包含多个数据对象的列表
library(tibble)
my_list <- lst(letters, mtcars, co2, uspop, iris)
任务。
我想修改
my_list$mtcars
为:- 重命名
cyl
列 - 计算一个新列,对
mpg
列中的值求平方根
- 重命名
我想修改
my_list$iris
为:- select 以
sepal
开头的列
- 将它们重命名为小写
最终我希望得到一个与原始
my_list
相同的列表对象,除了我对mtcars
和iris
.[=23= 所做的更改之外]- select 以
我的尝试。现在,我知道实现此目的的唯一方法涉及重新分配:
library(dplyr)
my_list$mtcars <-
my_list$mtcars %>%
rename("Number of cylinders" = cyl) %>%
mutate(sqrt_of_mpg = sqrt(mpg))
my_list$iris <-
my_list$iris %>%
select(starts_with("Sepal")) %>%
rename_with(tolower)
我的问题: 给定 my_list
,我如何通过名称指向嵌套元素,指定应该发生哪些操作来修改它,并取回parent my_list
只做了那些修改?
我想象某种管道看起来像这样(只是为了了解我的大致想法)
## DEMO ##
my_list %>%
update_element(which = "mtcars", what = rename, mutate) %>%
update_element(which = "iris", what = select, rename)
谢谢!
你可以试试purrr
的modify_at
功能
library(tidyverse)
my_list %>%
modify_at("mtcars", ~rename(.,"Number of cylinders" = cyl) %>%
mutate(sqrt_of_mpg = sqrt(mpg))) %>%
modify_at("iris", ~select(., starts_with("Sepal")) %>%
rename_with(tolower))
您可以使用 imap
为每次迭代传递名称和数据,但这并不接近您的总体想法。
library(dplyr)
my_list <- purrr::imap(my_list, ~{
if(.y == 'mtcars')
.x %>% rename("Number of cylinders" = cyl) %>%mutate(sqrt_of_mpg = sqrt(mpg))
else if(.y == 'iris')
.x %>% select(starts_with("Sepal")) %>% rename_with(tolower)
else .x
})