首页 > 解决方案 > 使用 purrr 在多个列表上迭代(非同时)?

问题描述

我想创建几个数据框,这些数据框使用我的数据集中的三个变量进行过滤: state是一个具有两个可能值的分类变量 -vaazlog_aa_3r并且log_lat_3r都是连续数值变量。

我想最终得到 4 个数据帧:每个状态 2 个,并且每个状态的 dfs 将被过滤,以便一个具有所有log_aa_3r有限的情况,而另一个将具有所有log_lat_3r有限的情况。

我可以手动执行此操作,如下所示:

library(tidyverse)
az_aa <- combine_dat %>%
  filter(state == "az" & is.finite(log_aa_3r))

az_lat <- combine_dat %>%
  filter(state == "az" & is.finite(log_lat_3r))

va_aa <- combine_dat %>%
  filter(state == "va" & is.finite(log_aa_3r))

va_lat <- combine_dat %>%
  filter(state == "va" & is.finite(log_lat_3r))

但是,我想弄清楚如何迭代地做到这一点。

我觉得我需要使用嵌套的 map 语句来解决这个问题,但我似乎不能完全正确地编写代码。我尝试了以下方法,它产生了我期望的输出结构,但是输出中的所有 dfs 都有 0 个观察值:

states <- list('az', 'va')
use_vars <- list('log_aa_3r', 'log_lat_3r')

dfs <- map(states, function(x)
           {map(use_vars,
                function(y) {comb_test %>%
                 filter(state == x & is.finite(y))}
                )}
           )

这里有一小部分数据可以帮助解决这个问题:

comb_test <- structure(list(state = c("az", "az", "va", "az", "az", "va", 
"va", "az", "va", "va", "az", "az", "az", "va", "az", "az", "va", 
"az", "az", "va"), log_aa_3r = c(0.122043015617762, NaN, 0.418616817019589, 
NaN, -0.237849698703905, 0.11553768471152, NA, -Inf, 0.253046912790677, 
0.71751672463271, -Inf, -Inf, -Inf, 0.125839047001367, -Inf, 
0.372823951010564, 0.43784426926065, -Inf, -Inf, NA), log_lat_3r = c(0.0393482723090127, 
-0.352428653057281, -0.0641399653902218, -0.306485199414877, 
-0.696871579650928, -0.191460177039553, NA, -0.361114213161674, 
-0.0786756534620034, 0.216382765848136, 0.0344915670084646, 0.00130866713103227, 
0.756875541289108, NA, -0.216873938300614, -0.0627820764799239, 
0.261387831919094, -0.018314845703395, -0.161990655409072, NA
)), row.names = c(NA, -20L), class = c("tbl_df", "tbl", "data.frame"
))

任何帮助将不胜感激!

编辑:

我使用以下代码让它工作。它可能不是最优雅的,因为我最终得到了tbl与变量名相同的名称,但它做了我想做的事情。

df2 <- 
  map(states, function(x) 
{map_at(combine_test, c("log_aa_3r", "log_lat_3r"), function(y) 
{combine_test %>%
    filter(state == x & is.finite(y))})}
  )

df_list <- list(az_aa = df2[[1]]$log_aa_3r, az_lat = df2[[1]]$log_lat_3r, 
                va_aa = df2[[2]]$log_aa_3r, va_lat = df2[[2]]$log_lat_3r)

标签: rpurrr

解决方案


这是执行此操作的一种方法。首先,您可以生成所有条件tidyr::crossing

states <- c('az', 'va')
use_vars <- c('log_aa_3r', 'log_lat_3r')
conditions <- tidyr::crossing(states, use_vars)

然后你可以purrr::pmap用来遍历这两个列表

purrr::pmap(conditions, function(states, use_vars) {
  comb_test %>% filter(state==!!(states) & is.finite(!!sym(use_vars)))
})

这里我们使用 splicing ( !!) 来插入值,并使用sym()将字符串版本的变量名变成符号


推荐阅读