使用R中的purrr包有条件地覆盖列表?

问题描述

我有下面的数据集。它包含三种状态下每一方候选人的非中心性参数(NCP),自由度(DF)和模拟次数(10,000)。如您所见,有些种族没有给定派对的候选人:

dat <- tibble(state = c("Iowa","Wisconsin","Minnesota"),ncp_D = c(0,11000,5700),ncp_R = c(10000,12000,5000),ncp_Ind = c(1800,600),df_D = c(10),df_R = c(10),df_Ind = c(10),sims_D = c(10000),sims_R = c(10000),sims_Ind = c(10000))

我希望代码使用purrr包为三个州的每个候选人产生10,000个模拟。以下是基于t分布(rt())用于启动此过程的代码

dat_results <- dat %>% 
  mutate(DVotes = pmap(list(sims_D,df_D,ncp_D),rt),RVotes = pmap(list(sims_R,df_R,ncp_R),IndVotes = pmap(list(sims_Ind,df_Ind,ncp_Ind),rt))

这将在dat_results数据帧中生成三个投票可能性列表,但是我最终希望为候选人生成的列表如果其ncp值为零,则该列表为零。例如,衣阿华州的D候选者应基于rt()函数将其预测值设为10,000个零,而不是使用0作为其NCP的值,从而得出一些负值。与威斯康星州的Ind候选人相同。本质上,我正在尝试有条件地覆盖数据框中的列表

在R中是否有一种简便的方法,最好使用purrr包?预先感谢。

解决方法

对于您而言,我认为最简单的方法就是更改rt()函数:

cond_rt <- function(n,df,ncp,...){
  if(ncp == 0) return(rep(0,n))
  rt(n,...)
}

然后只需使用该修改版本:

dat_results <- dat %>% 
  mutate(DVotes = pmap(list(sims_D,df_D,ncp_D),cond_rt),RVotes = pmap(list(sims_R,df_R,ncp_R),IndVotes = pmap(list(sims_Ind,df_Ind,ncp_Ind),cond_rt))

map_dbl(dat_results$DVotes,length)
#> [1] 10000 10000 10000
map_dbl(dat_results$DVotes,sum)
#> [1]         0 119262980  61756273

但是,如果您确实想有条件地修改列后验,则可以使用mutate()if_else()来完成。我们只是需要读写列表元素而遇到一个问题,可以通过rowwise()(一次读取单个行元素)并在输出上调用list()来解决此问题。我们获得了长度为1的列表,可以将其作为元素插入。


dat_results2 <- dat %>% 
  mutate(DVotes = pmap(list(sims_D,rt),rt)) %>%
  rowwise() %>%
  mutate(DVotes = if_else(ncp_D == 0,list(rep(0,length(DVotes))),list(DVotes)),RVotes = if_else(ncp_R == 0,length(RVotes))),list(RVotes)),IndVotes = if_else(ncp_Ind == 0,length(IndVotes))),list(IndVotes)))

map_dbl(dat_results2$DVotes,length)
#> [1] 10000 10000 10000
map_dbl(dat_results2$DVotes,sum)
#> [1]         0 119172966  61629269

可以用across()简化。