purrr pmap для списка-столбца и нескольких векторов - PullRequest
0 голосов
/ 06 июня 2019

Я учусь использовать мурлыканье и подумал, что было бы полезно отслеживать некоторые вычисления.

Однако я не уверен, почему я не могу выполнить определенную операцию, используя purrr :: pmap, включающий следующие компоненты:

Список с каждым элементом длины n Вектор длины 1 Вектор длины 1 Вектор длины n 1., 2. и 3. все находятся в одном и том же фрейме данных (с именем 'operations_df'). 4. находится вне фрейма данных, но является вектором одинаковой длины каждого элемента списка (которые имеют одинаковую длину). Таким образом, вызов функции в основном включает умножение каждого элемента в векторах 1. на каждый элемент в 4., а затем добавление / вычитание результирующих векторов 1 элемента с 2 и 3.

Это прекрасно работает, если я разбиваю вещи по функциям map2. Но мне интересно, как я могу заставить это работать в одной строке с pmap?

library(purrr)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

# generate data
data <- rbeta(n = 10, shape1 = 80, shape2 = 80)

prob_k1 <- rbeta(n = 10, shape1 = 80, shape2 = 10)
prob_k2 <- 1-prob_k1


# perform operations on prob_k and data in a data.frame
operations_df <- tibble(components = c('1', '2'),
                        probability = list(prob_k1, prob_k2)) %>%

  # sum over list column
  mutate(n = map_dbl(probability, sum)) %>%

  # mean for each row, using list column and a single 1-element vector
  mutate(mu = map2_dbl(probability, n, ~ (1/.y) * sum(data * .x))) 

operations_df
#> # A tibble: 2 x 4
#>   components probability     n    mu
#>   <chr>      <list>      <dbl> <dbl>
#> 1 1          <dbl [10]>   8.93 0.504
#> 2 2          <dbl [10]>   1.07 0.506

# this doesn't work
# variance for each row, using list column, and two 1-element vectors
operations_df %>%
  mutate(var = pmap_dbl(probability, n, mu, ~ (1/(..2-1)) * sum(..1 * data^2) - ..3^2))
#> Result 1 must be a single double, not NULL of length 0

# this does work
(1/(operations_df$n[1]-1)) * sum(operations_df$probability[[1]] * data^2) - operations_df$mu[1]^2
#> [1] 0.0342961
(1/(operations_df$n[2]-1)) * sum(operations_df$probability[[2]] * data^2) - operations_df$mu[2]^2
#> [1] 3.800814

# breaking it up into two map2 calls works:
operations_df %>%
  mutate(var = map2_dbl(n, probability, ~ (1/(.x-1)) * sum(.y * data^2))) %>%
  mutate(var = map2_dbl(var, mu, ~ .x - .y^2))
#> # A tibble: 2 x 5
#>   components probability     n    mu    var
#>   <chr>      <list>      <dbl> <dbl>  <dbl>
#> 1 1          <dbl [10]>   8.93 0.504 0.0343
#> 2 2          <dbl [10]>   1.07 0.506 3.80

1 Ответ

1 голос
/ 06 июня 2019

pmap() принимает только список параметров и не принимает их по одному за раз, как map() или map2(), поэтому вам нужно указать свои параметры в списке перед запуском преобразования.

library(purrr)
library(dplyr)

set.seed(10)

# generate data
data <- rbeta(n = 10, shape1 = 80, shape2 = 80)

prob_k1 <- rbeta(n = 10, shape1 = 80, shape2 = 10)
prob_k2 <- 1-prob_k1

# perform operations on prob_k and data in a data.frame
operations_df <- tibble(components = c('1', '2'),
                        probability = list(prob_k1, prob_k2)) %>%
    mutate(n = map_dbl(probability, sum)) %>%
    mutate(mu = map2_dbl(probability, n, ~ (1/.y) * sum(data * .x))) 

# pmap only takes a list and not parameters one at a time like map & map2
# see ?pmap for more deetz
operations_df %>%
    mutate(var = pmap_dbl(list(probability, n, mu), ~(1/(..2-1)) * sum(..1 * data^2) - ..3^2))
#> # A tibble: 2 x 5
#>   components probability     n    mu    var
#>   <chr>      <list>      <dbl> <dbl>  <dbl>
#> 1 1          <dbl [10]>   8.77 0.476 0.0303
#> 2 2          <dbl [10]>   1.23 0.479 1.01

# This produces the same output without the complication of thinking about mutate(). 
list(operations_df$probability, 
     operations_df$n, 
     operations_df$mu) %>% 
    pmap_dbl(~(1/(..2-1)) * sum(..1 * data^2) - ..3^2)
#> [1] 0.0303307 1.0087492

Создано в 2019-06-06 пакетом Представить (v0.2.1)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...