对每个字符向量应用 purrr::map
Applying purrr::map over each of a vector of characters
我正在努力更好地理解 purrr::map 函数。假设我有一个简单的字符向量,我想 运行 一些使用每个字符作为输入来输出数据框的函数。
这是一个玩具示例
animals <- c('sheep', 'cow', 'horse')
make_df <- function(x){
data.frame(r1 = rnorm(1:5), r2 = rnorm(1:5), an = x)
}
这是make_df
> make_df('sheep')
r1 r2 an
-0.18069698 -0.4767575 sheep
0.09580225 0.2785548 sheep
-0.74701529 0.2673391 sheep
-1.62795239 1.0026010 sheep
0.36573951 -0.2323944 sheep
现在,我想 运行 每个动物的这个函数并将每个数据框保存到一个列表中,然后将该列表放入一个新的数据框中,其中一列是动物,一列是列表数据框(我将与其他 tidyverse 函数一起使用)。
我认为这样做的方法是
data.frame(animals = animals) %>% mutate(ldf = map(animals, make_df(.)))
data.frame(animals = animals) %>% mutate(ldf = map(animals, make_df(.)))
但这给了我一个错误
Error in mutate_impl(.data, dots): Evaluation error: arguments imply differing number of rows: 5, 3. Traceback:
1. data.frame(animals = animals) %>% mutate(ldf = map(animals, make_df(.)))
2. withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
3. eval(quote(`_fseq`(`_lhs`)), env, env)
4. eval(quote(`_fseq`(`_lhs`)), env, env)
5. `_fseq`(`_lhs`)
6. freduce(value, `_function_list`)
7. withVisible(function_list[[k]](value))
8. function_list[[k]](value)
9. mutate(., ldf = map(animals, make_df(.)))
10. mutate.data.frame(., ldf = map(animals, make_df(.)))
11. as.data.frame(mutate(tbl_df(.data), ...))
12. mutate(tbl_df(.data), ...)
13. mutate.tbl_df(tbl_df(.data), ...)
14. mutate_impl(.data, dots)
当然,我可以用lapply
制作这个数据框列表
dfs <- lapply(animals, make_df)
但是如果我尝试将 dfs 和 animals 绑定到一个数据框中,我会得到一个看似相关的错误,同样是关于不同的行数。
data.frame(animals, dfs)
Error in data.frame(animals, dfs): arguments imply differing number of rows: 3, 5 Traceback:
1. data.frame(animals, dfs)
2. stop(gettextf("arguments imply differing number of rows: %s", . paste(unique(nrows), collapse = ", ")), domain = NA)
显然,我在这里遗漏了一些基本的东西。为什么我无法手动将字符列表和数据帧列表合并到一个数据帧中,我是如何滥用 purrr::map
以至于 R 运行s 成为一个问题,大概是试图做在我的职能中也是如此。
你的语法有点不对,你要么用map(animals, make_df)
要么map(animals, ~ make_df(.))
,map
的第二个参数需要是一个函数,这和lapply
:
data.frame(animals) %>% mutate(ldf = map(animals, make_df)) %>% as.tibble()
# A tibble: 3 x 2
# animals ldf
# <fctr> <list>
#1 sheep <data.frame [5 x 3]>
#2 cow <data.frame [5 x 3]>
#3 horse <data.frame [5 x 3]>
data.frame(animals) %>% mutate(ldf = map(animals, ~ make_df(.))) %>% as.tibble()
# A tibble: 3 x 2
# animals ldf
# <fctr> <list>
#1 sheep <data.frame [5 x 3]>
#2 cow <data.frame [5 x 3]>
#3 horse <data.frame [5 x 3]>
或者如果使用data.frame
构造函数,则需要使用I
创建列表类型的列:
data.frame(animals, ldf = I(lapply(animals, make_df)))
# ^
我正在努力更好地理解 purrr::map 函数。假设我有一个简单的字符向量,我想 运行 一些使用每个字符作为输入来输出数据框的函数。
这是一个玩具示例
animals <- c('sheep', 'cow', 'horse')
make_df <- function(x){
data.frame(r1 = rnorm(1:5), r2 = rnorm(1:5), an = x)
}
这是make_df
> make_df('sheep')
r1 r2 an
-0.18069698 -0.4767575 sheep
0.09580225 0.2785548 sheep
-0.74701529 0.2673391 sheep
-1.62795239 1.0026010 sheep
0.36573951 -0.2323944 sheep
现在,我想 运行 每个动物的这个函数并将每个数据框保存到一个列表中,然后将该列表放入一个新的数据框中,其中一列是动物,一列是列表数据框(我将与其他 tidyverse 函数一起使用)。
我认为这样做的方法是
data.frame(animals = animals) %>% mutate(ldf = map(animals, make_df(.)))
data.frame(animals = animals) %>% mutate(ldf = map(animals, make_df(.)))
但这给了我一个错误
Error in mutate_impl(.data, dots): Evaluation error: arguments imply differing number of rows: 5, 3. Traceback: 1. data.frame(animals = animals) %>% mutate(ldf = map(animals, make_df(.))) 2. withVisible(eval(quote(`_fseq`(`_lhs`)), env, env)) 3. eval(quote(`_fseq`(`_lhs`)), env, env) 4. eval(quote(`_fseq`(`_lhs`)), env, env) 5. `_fseq`(`_lhs`) 6. freduce(value, `_function_list`) 7. withVisible(function_list[[k]](value)) 8. function_list[[k]](value) 9. mutate(., ldf = map(animals, make_df(.))) 10. mutate.data.frame(., ldf = map(animals, make_df(.))) 11. as.data.frame(mutate(tbl_df(.data), ...)) 12. mutate(tbl_df(.data), ...) 13. mutate.tbl_df(tbl_df(.data), ...) 14. mutate_impl(.data, dots)
当然,我可以用lapply
dfs <- lapply(animals, make_df)
但是如果我尝试将 dfs 和 animals 绑定到一个数据框中,我会得到一个看似相关的错误,同样是关于不同的行数。
data.frame(animals, dfs)
Error in data.frame(animals, dfs): arguments imply differing number of rows: 3, 5 Traceback: 1. data.frame(animals, dfs) 2. stop(gettextf("arguments imply differing number of rows: %s", . paste(unique(nrows), collapse = ", ")), domain = NA)
显然,我在这里遗漏了一些基本的东西。为什么我无法手动将字符列表和数据帧列表合并到一个数据帧中,我是如何滥用 purrr::map
以至于 R 运行s 成为一个问题,大概是试图做在我的职能中也是如此。
你的语法有点不对,你要么用map(animals, make_df)
要么map(animals, ~ make_df(.))
,map
的第二个参数需要是一个函数,这和lapply
:
data.frame(animals) %>% mutate(ldf = map(animals, make_df)) %>% as.tibble()
# A tibble: 3 x 2
# animals ldf
# <fctr> <list>
#1 sheep <data.frame [5 x 3]>
#2 cow <data.frame [5 x 3]>
#3 horse <data.frame [5 x 3]>
data.frame(animals) %>% mutate(ldf = map(animals, ~ make_df(.))) %>% as.tibble()
# A tibble: 3 x 2
# animals ldf
# <fctr> <list>
#1 sheep <data.frame [5 x 3]>
#2 cow <data.frame [5 x 3]>
#3 horse <data.frame [5 x 3]>
或者如果使用data.frame
构造函数,则需要使用I
创建列表类型的列:
data.frame(animals, ldf = I(lapply(animals, make_df)))
# ^