bars - Ist es möglich, NA-Werte im Operator "+" zu überspringen?




r barplot labels (4)

Ich möchte eine Gleichung in R berechnen. Ich möchte die Funktion sum weil sie 1 Wert zurückgibt. Ich möchte den vollständigen Vektor der Werte.

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

Ich will nicht:

sum(x,y, na.rm = TRUE)
[1] 280

Welches gibt keinen Vektor zurück.

Dies ist ein Spielzeug-Beispiel, aber ich habe eine komplexere Gleichung mit mehreren Vektoren der Länge 84647 Elemente.

Hier ist ein weiteres Beispiel, was ich meine:

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

Nur für 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

was wiederum die Tatsache veranschaulicht, dass alles in R eine Funktion ist (und zeigt auch, dass der R-Interpreter schlau genug ist, eine Zeichenkette bei Bedarf in eine Funktion zu verwandeln).

Syntaktisch gesüßt:

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

Allgemeingültigere Version:

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

Sie können 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

1)% +% Definieren Sie einen benutzerdefinierten Operator +:

`%+%` <- function(x, y)  mapply(sum, x, y, MoreArgs = list(na.rm = TRUE))
5 + 2 * (x %+% y - 50) / (x %+% y %+% z %+% a)

geben:

[1] 3.303030 3.555556 3.769231 4.388889 4.473684 4.550000 4.619048 4.681818
[9] 4.739130 3.787879

Hier sind einige einfache Beispiele:

1 %+% 2
## [1] 3

NA %+% 2
## [1] 2

2 %+% NA
## [1] 2

NA %+% NA
## [1] 0

2) na2zero Eine andere Möglichkeit besteht darin, eine Funktion zu definieren, die NA wie folgt auf 0 abbildet:

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)

geben:

[1] 3.303030 3.555556 3.769231 4.388889 4.473684 4.550000 4.619048 4.681818
[9] 4.739130 3.787879

3) Kombiniere oben Eine Variation, die (1) mit der Idee in (2) kombiniert, ist:

X <- x %+% 0
Y <- y %+% 0
Z <- z %+% 0
A <- a %+% 0

5 + 2 * (X + Y - 50) / (X + Y + Z + A)

4) numeric0 class Wir können eine benutzerdefinierte Klasse "numeric0" mit einem eigenen + Operator definieren:

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)

Anmerkung: Die verwendeten Eingaben waren diejenigen in der Frage, nämlich:

x = 1:10
y = c(21:29,NA)
z = 11:20
a = c(NA,NA,NA,30:36)

rowSums :

Um meinen Kommentar näher auszuführen, können Sie die Vektoren verketten und dann Ihre Berechnungen auf die resultierende Matrix anwenden. Dies ist die Lösung für das Beispiel, das Sie am Ende Ihrer Frage angegeben haben.

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

Neufassung von NA :

Ich habe hier Lösungen mit der Idee gesehen, NA in den Vektoren zu ersetzen; Ich denke, das wäre auch hilfreich:

y[is.na(y)] <- 0 #indexing NA values and replacing with zero