dplyr mutate не применяется к отдельному элементу поля - PullRequest
0 голосов
/ 14 сентября 2018

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

Вот воспроизводимый пример:

library(dplyr)
#the data
dd <- structure(list(fire_zone = c("ET", "EJB", "WJB"), base_med = c(1, 1, 2)), class = "data.frame", row.names = c(NA, -3L))

# my home made function
med2lambda <- function(med) polyroot(c(-0.02, 1/3 - med, 1)) %>% {suppressWarnings(as.numeric(.))} %>% max

Итак, моя функция заключается в оценке лямбды, связанной с медианой из распределения Пуассона, путем вычисления корня квадратичной функции. Несмотря на длинное объяснение, на самом деле оно довольно простое:

med2lambda(1)
[1] 0.695426
med2lambda(2)
[1] 1.678581

Теперь я хочу использовать его в вызове mutate, чтобы добавить поле, дающее лямбду, связанную с каждой медианой в таблице:

dd %>% mutate(lambda = med2lambda(base_med), log = log(base_med))
fire_zone base_med   lambda       log
1        ET        1 2.128966 0.0000000
2       EJB        1 2.128966 0.0000000
3       WJB        2 2.128966 0.6931472

Результат неверный, мутация фактически дает мне результаты:

med2lambda(dd$base_med)
[1] 2.128966

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

Любое понимание этого поведения приветствуется.

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Мы можем использовать map

library(tidyverse)
dd %>% 
    mutate(lambda = map_dbl(base_med, med2lambda), log = log(base_med))
0 голосов
/ 14 сентября 2018

Вам нужно разрешить med2lambda принимать векторы вместо скаляров.

Одна из возможностей - использовать Vectorize:

med2lambda.vectorised <- Vectorize(med2lambda)
dd %>% mutate(lambda = med2lambda.vectorised(base_med), log = log(base_med))
#  fire_zone base_med   lambda       log
#1        ET        1 0.695426 0.0000000
#2       EJB        1 0.695426 0.0000000
#3       WJB        2 1.678581 0.6931472

В качестве альтернативы, вы можете переписать med2lambda ввзять вектор в качестве аргумента:

med2lambda2 <- function(med) sapply(med, function(x)
    polyroot(c(-0.02, 1/3 - x, 1)) %>% {suppressWarnings(as.numeric(.))} %>% max)
dd %>% mutate(lambda = med2lambda2(base_med), log = log(base_med))
#  fire_zone base_med   lambda       log
#1        ET        1 0.695426 0.0000000
#2       EJB        1 0.695426 0.0000000
#3       WJB        2 1.678581 0.6931472
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...