Я думаю, вы думаете, что здесь слишком сложно. Что не так с двумя отдельными apply()
звонками? Тем не менее, есть гораздо лучший способ сделать то, что вы делаете здесь, который не включает зацикливание / применение вызовов Я рассмотрю их отдельно, но второе решение предпочтительнее, поскольку оно действительно векторизовано.
Версия двух звонков
Первые два отдельных прикладных вызова с использованием всех базовых функций R:
df1 <- data.frame(Bar1=c(1,2,3,-3,-2,-1),Bar2=c(3,1,3,-2,-3,-1))
df1 <- transform(df1, MFE = apply(df1, 1, FindMFE), MAE = apply(df1, 1, FindMAE))
df1
Что дает:
> df1
Bar1 Bar2 MFE MAE
1 1 3 3 0
2 2 1 2 0
3 3 3 3 0
4 -3 -2 0 -3
5 -2 -3 0 -3
6 -1 -1 0 -1
Хорошо, повторение над строками df1
дважды, возможно, немного неэффективно, но даже для больших проблем вы уже потратили больше времени , думая о том, чтобы сделать это умно за один проход, чем вы будете сохранить таким образом.
Использование векторизованных функций pmax()
и pmin()
Итак, лучший способ сделать это - отметить функции pmax()
и pmin()
и понять, что они могут делать то, что делал каждый из вызовов apply(df1, 1, FindFOO()
. Например:
> (tmp <- with(df1, pmax(0, Bar1, Bar2, na.rm = TRUE)))
[1] 3 2 3 0 0 0
будет MFE от вашего вопроса. С этим очень просто работать, если у вас есть два столбца, и они всегда Bar1
и Bar2
или первые 2 столбца df1
. Но это не очень общее; Что делать, если у вас есть несколько столбцов, которые вы хотите вычислить и т.д.? pmax(df1[, 1:2], na.rm = TRUE)
не будет делать то, что мы хотим:
> pmax(df1[, 1:2], na.rm = TRUE)
Bar1 Bar2
1 1 3
2 2 1
3 3 3
4 -3 -2
5 -2 -3
6 -1 -1
Хитрость в получении общего решения с использованием pmax()
и pmin()
заключается в использовании do.call()
для организации вызовов этих двух функций для нас. Обновляя ваши функции, чтобы использовать эту идею, мы имеем:
FindMFE2 <- function(x) {
MFE <- do.call(pmax, c(as.list(x), 0, na.rm = TRUE))
MFE[is.infinite(MFE)] <- 0
MFE
}
FindMAE2 <- function(x) {
MAE <- do.call(pmin, c(as.list(x), 0, na.rm = TRUE))
MAE[is.infinite(MAE)] <- 0
MAE
}
которые дают:
> transform(df1, MFE = FindMFE2(df1), MAE = FindMAE2(df1))
Bar1 Bar2 MFE MAE
1 1 3 3 0
2 2 1 2 0
3 3 3 3 0
4 -3 -2 0 -3
5 -2 -3 0 -3
6 -1 -1 0 -1
а не apply()
в поле зрения. Если вы хотите сделать это за один шаг, теперь это гораздо проще обернуть:
FindMAEandMFE2 <- function(x){
cbind(MFE = FindMFE2(x), MAE = FindMAE2(x))
}
, который можно использовать как:
> cbind(df1, FindMAEandMFE2(df1))
Bar1 Bar2 MFE MAE
1 1 3 3 0
2 2 1 2 0
3 3 3 3 0
4 -3 -2 0 -3
5 -2 -3 0 -3
6 -1 -1 0 -1