Можно ли пропускать значения NA в операторе "+"?
Я хочу рассчитать уравнение в R. Я не хочу использовать функцию sum
, потому что она возвращает 1 значение. Я хочу полный вектор значений.
x = 1:10
y = c(21:29,NA)
x+y
[1] 22 24 26 28 30 32 34 36 38 NA
x = 1:10
y = c(21:30)
x+y
[1] 22 24 26 28 30 32 34 36 38 40
Я не хочу:
sum(x,y, na.rm = TRUE)
[1] 280
Что не возвращает вектор.
Это пример игрушки, но у меня есть более сложное уравнение, использующее несколько векторов длиной 84647 элементов.
Вот еще один пример того, что я имею в виду:
x = 1:10
y = c(21:29,NA)
z = 11:20
a = c(NA,NA,NA,30:36)
5 +2*(x+y-50)/(x+y+z+a)
[1] NA NA NA 4.388889 4.473684 4.550000 4.619048 4.681818 4.739130 NA
Ответы
Ответ 1
1)% +% Определите пользовательский + оператор:
`%+%` <- function(x, y) mapply(sum, x, y, MoreArgs = list(na.rm = TRUE))
5 + 2 * (x %+% y - 50) / (x %+% y %+% z %+% a)
даяние:
[1] 3.303030 3.555556 3.769231 4.388889 4.473684 4.550000 4.619048 4.681818
[9] 4.739130 3.787879
Вот несколько простых примеров:
1 %+% 2
## [1] 3
NA %+% 2
## [1] 2
2 %+% NA
## [1] 2
NA %+% NA
## [1] 0
2) na2zero Другая возможность - определить функцию, которая отображает NA в 0 следующим образом:
na2zero <- function(x) ifelse(is.na(x), 0, x)
X <- na2zero(x)
Y <- na2zero(y)
Z <- na2zero(z)
A <- na2zero(a)
5 + 2 * (X + Y - 50) / (X + Y + Z + A)
даяние:
[1] 3.303030 3.555556 3.769231 4.388889 4.473684 4.550000 4.619048 4.681818
[9] 4.739130 3.787879
3) объединить выше. Комбинация вариантов (1) с идеей в (2):
X <- x %+% 0
Y <- y %+% 0
Z <- z %+% 0
A <- a %+% 0
5 + 2 * (X + Y - 50) / (X + Y + Z + A)
4) numeric0 class Мы можем определить пользовательский класс "numeric0"
со своим оператором +:
as.numeric0 <- function(x) structure(x, class = "numeric0")
`+.numeric0` <- `%+%`
X <- as.numeric0(x)
Y <- as.numeric0(y)
Z <- as.numeric0(z)
A <- as.numeric0(a)
5 + 2 * (X + Y - 50) / (X + Y + Z + A)
Примечание: В качестве входных данных использовались следующие вопросы:
x = 1:10
y = c(21:29,NA)
z = 11:20
a = c(NA,NA,NA,30:36)
Ответ 2
Использование rowSums
:
Чтобы уточнить мой комментарий, вы можете конкатенировать векторы, а затем применить свои вычисления на приведенной матрице. Это решение для примера, предоставленного вами в конце вашего вопроса;
5 + 2 * (rowSums(cbind(x,y), na.rm = T)-50)/(rowSums(cbind(x,y,z,a), na.rm = T))
# [1] 3.303030 3.555556 3.769231 4.388889 4.473684 4.550000 4.619048 4.681818
# [9] 4.739130 3.787879
Отталкивание NA
:
Я видел решения здесь с идеей замены NA
на векторы; Я думаю, что это тоже было бы полезно:
y[is.na(y)] <- 0 #indexing NA values and replacing with zero
Ответ 3
вы можете использовать ifelse()
x = 1:10
y = c(21:29,NA)
x+y
[1] 22 24 26 28 30 32 34 36 38 NA
x + ifelse(is.na(y), 0, y)
[1] 22 24 26 28 30 32 34 36 38 10
Ответ 4
DATA
x = 1:10
y = c(21:29,NA)
x+y
# [1] 22 24 26 28 30 32 34 36 38 NA
1
foo1 = function(...){
return(rowSums(cbind(...), na.rm = TRUE))
}
foo1(x, y)
# [1] 22 24 26 28 30 32 34 36 38 10
2
foo2 = function(...){
Reduce('+', lapply(list(...), function(x) replace(x, is.na(x), 0)))
}
foo2(x, y)
# [1] 22 24 26 28 30 32 34 36 38 10
Ответ 5
Только для laffs:
x=1:10
y=c(21:29, NA)
"[<-"(x, is.na(x), 0) + "[<-"(y, is.na(y), 0)
# [1] 22 24 26 28 30 32 34 36 38 10
что еще раз иллюстрирует тот факт, что все в R является функцией (а также показывает, что интерпретатор R достаточно умен, чтобы при необходимости преобразовывать строку в функцию).
Синтаксически подслащенный:
na.zero <- function(x)
{
"[<-"(x, is.na(x), 0)
}
na.zero(x) + na.zero(y)
# [1] 22 24 26 28 30 32 34 36 38 10
Более широко применимая версия:
na.replace <- function(x, value)
{
"[<-"(x, is.na(x), value)
}
na.replace(x, 1) * na.replace(x, 1)
# [1] 1 4 9 16 25 36 49 64 81 100