При запуске функции в R с использованием mapply вывод, который я наблюдаю, не соответствует ожиданиям - PullRequest
0 голосов
/ 09 апреля 2020

Я хочу запустить функцию и извлечь выходные данные для объектов внутри функции. Результат, который я ожидаю, представляет собой фрейм данных с 5 строками и 5 столбцами. Вместо этого я получаю 1000 строк с 5 столбцами.

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

input.rows3 <- data.frame(pd=c(38, 50, 50, 86, 38),
                          Cl=c(15, 40, 30, 81, 15),
                          va=c(150, 145, 160, 141, 150),
                          co=c(3.0, 4.5, 4.0, 4.8, 1.5))

P <- c(seq(0,184,length.out=1000))

deriv.model <- function(a,b,c,x){
        (a*exp(-((((exp(b)*x))/1000))+c+b))/1000
}

marg.N.resp.function3 <- function(va, co, pd, Cl, P){
        a <-  10000  + 20*Cl
        b <- 2
        c <- (-0.05*pd)
        pr <- co / (va/1000)
        optimalP <- as.data.frame(deriv.model(a,b,c,P)) %>% 
                rename(optimalP = "deriv.model(a, b, c, P)") %>% 
                mutate(diff=abs(optimalP - pr))
        resultP <-cbind(optimalP,P) %>%
                slice(which.min(diff)) %>% 
                select(P)
        newlist <- list(a, b, c, pr, resultP)
        return(newlist)

}

results3 <- as.data.frame(t(mapply(marg.N.resp.function3, 
                                   input.rows3$va, 
                                   input.rows3$co, 
                                   input.rows3$pd,
                                   input.rows3$Cl,
                                   P))) 

results3

Насколько я понимаю, последний столбец объекта results3 должен быть единственным значением, полученным из resultP. Тем не менее, похоже, что я получаю весь P вектор (последний столбец вывода), который я использую в качестве входных данных. Я, вероятно, делаю что-то не так с функцией (m) apply, для которой я не очень знаком.

Любая подсказка будет оценена.

Спасибо.

1 Ответ

1 голос
/ 09 апреля 2020

Передав P в качестве аргумента mapply, вы перебираете его и перерабатываете свои более короткие переменные. Два способа обойти это, в зависимости от того, как вы планируете использовать это, вы можете либо убрать P из списка аргументов и вызова mapply, либо создать список, который повторяет P один раз для каждой итерации.

При первом подходе измените определение функции, удалив «P» из списка аргументов:

library(tidyverse) # for %>%

marg.N.resp.function4 <- function(va, co, pd, Cl){
      a <-  10000  + 20*Cl
      b <- 2
      c <- (-0.05*pd)
      pr <- co / (va/1000)
      optimalP <- as.data.frame(deriv.model(a,b,c,P)) %>% 
            rename(optimalP = "deriv.model(a, b, c, P)") %>% 
            mutate(diff=abs(optimalP - pr))
      resultP <-cbind(optimalP,P) %>%
            slice(which.min(diff)) %>% 
            select(P)
      newlist <- list(a, b, c, pr, resultP)
      return(newlist)

}



results4 <- as.data.frame(t(mapply(marg.N.resp.function4, 
                                   input.rows3$va, 
                                   input.rows3$co, 
                                   input.rows3$pd,
                                   input.rows3$Cl 

                                   ))) 

results4

# V1 V2   V3       V4      V5
# 1 10300  2 -1.9       20       0
# 2 10800  2 -2.5 31.03448       0
# 3 10600  2 -2.5       25       0
# 4 11620  2 -4.3 34.04255       0
# 5 10300  2 -1.9       10 17.4975

Этот подход зависит от определения P вне функции. Если вы вызываете с разными векторами P, вам нужно будет переназначать P вне функции перед каждым запуском.

Второй подход будет более универсальным и позволит вам использовать другие векторы для P в разных запусках.

results3 <- as.data.frame(t(mapply(marg.N.resp.function3, 
                                   input.rows3$va, 
                                   input.rows3$co, 
                                   input.rows3$pd,
                                   input.rows3$Cl,
                                   list(rep(P, times = 5))

))) 

results3
# V1 V2   V3       V4      V5
# 1 10300  2 -1.9       20       0
# 2 10800  2 -2.5 31.03448       0
# 3 10600  2 -2.5       25       0
# 4 11620  2 -4.3 34.04255       0
# 5 10300  2 -1.9       10 17.4975

identical(results4, results3)
# [1] TRUE
...