Передача нескольких переменных элемента в функцию с помощью mutate создает NA? - PullRequest
0 голосов
/ 13 мая 2019

Пожалуйста, посоветуйте, у меня есть следующая простая функция:

mifflin_equation <- function(gender = "M", 
                             w_kg = 50,
                             h_cm = 180, 
                             age = 40,
                             activity_type = "sedentary") {

  activity_types <- c("sedentary", "light", "moderate", "active")

  if (!(tolower(activity_type) %in% activity_types)) {

    activity_type <- "sedentary"

  }

  activity_trans_table <- tibble(type = activity_types,
                                 activity_coeff = c(1.2, 1.375, 
                                                    1.55, 1.725))

  activity_coeff <- activity_trans_table$activity_coeff[activity_trans_table$type == tolower(activity_type)]

  common_equation <- (10 * w_kg) + (6.25 * h_cm) - (5 * age)

  if (gender == "M") {

    return((common_equation + 5) * activity_coeff)

  } else if (gender == "F") {

    return((common_equation - 161) * activity_coeff)

  }

}

Я строю некоторые опции:

age <- seq.int(30,90)
h <- seq.int(150, 200)
w <- seq.int(40, 150)
activity <- c("sedentary", "light", "moderate", "active")
gender <- c("M", "F")

all_options <- expand.grid(age = age, h = h, w = w, activity = activity, gender = gender)

Но когда я пытаюсь dplyr :: преобразовать вычисляемое полеиз вышеупомянутой функции я получаю первое вычисление в порядке и все NA:

mifflin_options <- all_options %>%
  dplyr::mutate(mifflin_eq_calories = mifflin_equation(gender = gender, 
                                                       w_kg = w, 
                                                       h_cm = h,
                                                       age = age,
                                                       activity_type = activity))

Я знаю, что если бы это была только одна переменная, я должен использовать sapply, но какое здесь решение?

Ответы [ 2 ]

2 голосов
/ 13 мая 2019

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

library(dplyr)
library(purrr)
temp <- head(all_options)

1) rowwise

temp %>%
  rowwise() %>%
  mutate(mifflin_eq_calories = mifflin_equation(gender = gender, 
                                                   w_kg = w, 
                                                   h_cm = h,
                                                   age = age,
                                                   activity_type = activity))

2) pmap

temp %>% mutate(mifflin_eq_calories = pmap_dbl(
            list(gender, w, h, age, activity), mifflin_equation))

3) База R mapply

mapply(mifflin_equation, temp$gender, temp$w, temp$h, temp$age, temp$activity)

4) Vectorize ваша функция

new_fun <- Vectorize(mifflin_equation)

4a) применить, используя mutate

temp %>%
 mutate(mifflin_eq_calories = new_fun(gender = gender, 
                                      w_kg = w, 
                                      h_cm = h,
                                      age = age,
                                      activity_type = activity))

4b) Или напрямую

new_fun(temp$gender, temp$w, temp$h, temp$age, temp$activity)

5) data.table

library(data.table)
setDT(temp)[, ans:= mifflin_equation(gender, w, h, age, activity),by = 1:nrow(temp)]
1 голос
/ 13 мая 2019

Мы можем использовать Map от base R

temp <- head(all_options)
unlist(do.call(Map, c(f = mifflin_equation, temp)))
...