Условная перезапись списка с использованием пакета purrr в R?

#r #purrr

#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, 0, 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))
  

Я хотел бы, чтобы код произвел 10000 симуляций для каждого кандидата в трех состояниях с использованием purrr пакета. Ниже приведен код, который я использую для запуска этого процесса на основе 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), rt),
         IndVotes = pmap(list(sims_Ind, df_Ind, ncp_Ind), rt))
  

Это создает три списка возможностей голосования в dat_results фрейме данных, но в конечном итоге я хочу, чтобы списки, созданные для кандидата, были полны нулей, если их значение ncp равно нулю. Например, у кандидата D в Айове должны быть предсказанные значения, основанные на rt() функции, равными 10000 нулям вместо значений, которые используют 0 в качестве своего NCP, что приводит к некоторым отрицательным значениям. То же самое с кандидатом Ind в Висконсине. По сути, я пытаюсь условно перезаписать список во фрейме данных.

Есть ли простой способ сделать это в R, предпочтительно используя purrr пакет? Заранее спасибо.

Ответ №1:

В вашем случае, я думаю, проще всего изменить rt() функцию:

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

Затем просто используйте эту измененную версию:

 dat_results <- dat %>% 
  mutate(DVotes = pmap(list(sims_D, df_D, ncp_D), cond_rt),
         RVotes = pmap(list(sims_R, df_R, ncp_R), cond_rt),
         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, df_D, ncp_D), rt),
         RVotes = pmap(list(sims_R, df_R, ncp_R), rt),
         IndVotes = pmap(list(sims_Ind, df_Ind, ncp_Ind), rt)) %>%
  rowwise() %>%
  mutate(DVotes = if_else(ncp_D == 0, list(rep(0, length(DVotes))), list(DVotes)),
         RVotes = if_else(ncp_R == 0, list(rep(0, length(RVotes))), list(RVotes)),
         IndVotes = if_else(ncp_Ind == 0, list(rep(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() .

Комментарии:

1. Спасибо за это, @Alexlok. Краткий вопрос: допустим, я хочу, чтобы функция cond_rt возвращала только неотрицательные значения. (То есть любые отрицательные значения, возвращаемые функцией, преобразуются в ноль.) Прямо сейчас, если NCP чуть выше нуля, функция вернет отрицательные значения, поскольку она следует правилам t-распределения. У вас есть предложения о том, как реализовать это в логике функции? Еще раз спасибо.

2. Простое установление порога должно работать: x <- rt(...); x[x<0] <- 0 . Но результирующее распределение больше не является надлежащим нецентральным распределением t, поэтому я не знаю, будет ли анализ по-прежнему правильным.