Tidyeval:将函数应用于从列表中提取的数据框
Tidyeval: apply function to data frames extracted from list
这是涉及包含复杂 table 的大型列表的问题的简化版本。我想从列表中提取 tables 并为每个应用一个函数。在这里,我们可以创建一个包含小型命名数据框的简单列表:
library(tidyverse)
table_names <- c('dfA', 'dfB', 'dfC')
dfA <- tibble(a = 1:3, b = 4:6, c = 7:9)
dfB <- tibble(a = 10:12, b = 13:15, c = 16:18)
dfC <- tibble(a = 19:21, b = 22:24, c = 25:27)
df_list <- list(dfA, dfB, dfC) %>% setNames(table_names)
这是我想要应用的操作类型的简化示例:
dfA_mod <- df_list$dfA %>%
mutate(name = 'dfA') %>%
select(name, everything())
在此示例中,我提取列表 df_list$dfA
中的三个 table 之一,在每一行中创建一个具有相同值的新列 mutate(name = 'dfA')
,然后重新排序列,以便新列出现在最左侧的位置 select(name, everything())
。生成的对象分配给 dfA_mod
.
为了解决更大的问题,我想使用 purrr::map()
变体之一将函数应用于字符向量 table_names
,这是在上面的第一段代码中启动的。 table_names
的元素有两个用途:1) 命名列表中的 table;和 2) 为修改后的 table.
中的 name
列提供值
我可以编写如下函数:
fun <- function(x) {
df_list$x %>%
mutate(name = x) %>%
select(name, everything()) %>%
assign(paste0(x, '_mod'), ., envir = .GlobalEnv)
}
然后使用map()
创建一个新的修改列表tables:
new_list <- df_list %>% map(table_name, fun(x))
但是当然这段代码不起作用,主要障碍是(至少对我而言)弄清楚如何在函数中引用和取消引用正确的术语。我是整洁评估的初学者,我可以在指定函数和正确使用 map
方面使用一些帮助。
这是所需的输出(修改后的 table):
# A tibble: 3 x 4
name a b c
<chr> <int> <int> <int>
1 dfA 1 4 7
2 dfA 2 5 8
3 dfA 3 6 9
在此先感谢您的帮助!
我们可以使用 purrr::imap
传递列表中的数据以及列表的名称
library(dplyr)
library(purrr)
df_out <- imap(df_list, ~.x %>% mutate(name = .y) %>% select(name, everything()))
df_out
#$dfA
# A tibble: 3 x 4
# name a b c
# <chr> <int> <int> <int>
#1 dfA 1 4 7
#2 dfA 2 5 8
#3 dfA 3 6 9
#$dfB
# A tibble: 3 x 4
# name a b c
# <chr> <int> <int> <int>
#1 dfB 10 13 16
#....
#....
这给出了所需数据帧的列表,如果您希望它们作为单独的数据帧,您可以这样做
names(df_out) <- paste0(names(df_out), "_mod")
list2env(df_out, .GlobalEnv)
我们也可以使用 base R Map
df_out <- Map(function(x, y) transform(x, name = y)[c('name', names(x))],
df_list, names(df_list))
并给出与上面相同的列表名称。
我们可以将其转换为带有 map
的单个 data.frame,同时传递 .id
library(purrr)
map_dfr(df_list, I, .id = 'name')
或 bind_rows
library(dplyr)
bind_rows(df_list, .id = 'name')
# A tibble: 9 x 4
# name a b c
# <chr> <int> <int> <int>
#1 dfA 1 4 7
#2 dfA 2 5 8
#3 dfA 3 6 9
#4 dfB 10 13 16
#5 dfB 11 14 17
#6 dfB 12 15 18
#7 dfC 19 22 25
#8 dfC 20 23 26
#9 dfC 21 24 27
这是涉及包含复杂 table 的大型列表的问题的简化版本。我想从列表中提取 tables 并为每个应用一个函数。在这里,我们可以创建一个包含小型命名数据框的简单列表:
library(tidyverse)
table_names <- c('dfA', 'dfB', 'dfC')
dfA <- tibble(a = 1:3, b = 4:6, c = 7:9)
dfB <- tibble(a = 10:12, b = 13:15, c = 16:18)
dfC <- tibble(a = 19:21, b = 22:24, c = 25:27)
df_list <- list(dfA, dfB, dfC) %>% setNames(table_names)
这是我想要应用的操作类型的简化示例:
dfA_mod <- df_list$dfA %>%
mutate(name = 'dfA') %>%
select(name, everything())
在此示例中,我提取列表 df_list$dfA
中的三个 table 之一,在每一行中创建一个具有相同值的新列 mutate(name = 'dfA')
,然后重新排序列,以便新列出现在最左侧的位置 select(name, everything())
。生成的对象分配给 dfA_mod
.
为了解决更大的问题,我想使用 purrr::map()
变体之一将函数应用于字符向量 table_names
,这是在上面的第一段代码中启动的。 table_names
的元素有两个用途:1) 命名列表中的 table;和 2) 为修改后的 table.
name
列提供值
我可以编写如下函数:
fun <- function(x) {
df_list$x %>%
mutate(name = x) %>%
select(name, everything()) %>%
assign(paste0(x, '_mod'), ., envir = .GlobalEnv)
}
然后使用map()
创建一个新的修改列表tables:
new_list <- df_list %>% map(table_name, fun(x))
但是当然这段代码不起作用,主要障碍是(至少对我而言)弄清楚如何在函数中引用和取消引用正确的术语。我是整洁评估的初学者,我可以在指定函数和正确使用 map
方面使用一些帮助。
这是所需的输出(修改后的 table):
# A tibble: 3 x 4
name a b c
<chr> <int> <int> <int>
1 dfA 1 4 7
2 dfA 2 5 8
3 dfA 3 6 9
在此先感谢您的帮助!
我们可以使用 purrr::imap
传递列表中的数据以及列表的名称
library(dplyr)
library(purrr)
df_out <- imap(df_list, ~.x %>% mutate(name = .y) %>% select(name, everything()))
df_out
#$dfA
# A tibble: 3 x 4
# name a b c
# <chr> <int> <int> <int>
#1 dfA 1 4 7
#2 dfA 2 5 8
#3 dfA 3 6 9
#$dfB
# A tibble: 3 x 4
# name a b c
# <chr> <int> <int> <int>
#1 dfB 10 13 16
#....
#....
这给出了所需数据帧的列表,如果您希望它们作为单独的数据帧,您可以这样做
names(df_out) <- paste0(names(df_out), "_mod")
list2env(df_out, .GlobalEnv)
我们也可以使用 base R Map
df_out <- Map(function(x, y) transform(x, name = y)[c('name', names(x))],
df_list, names(df_list))
并给出与上面相同的列表名称。
我们可以将其转换为带有 map
的单个 data.frame,同时传递 .id
library(purrr)
map_dfr(df_list, I, .id = 'name')
或 bind_rows
library(dplyr)
bind_rows(df_list, .id = 'name')
# A tibble: 9 x 4
# name a b c
# <chr> <int> <int> <int>
#1 dfA 1 4 7
#2 dfA 2 5 8
#3 dfA 3 6 9
#4 dfB 10 13 16
#5 dfB 11 14 17
#6 dfB 12 15 18
#7 dfC 19 22 25
#8 dfC 20 23 26
#9 dfC 21 24 27