2017-02-24 3 views
2

Das mag trivial, aber ich habe einen Code, der den Durchschnitt der nächsten zwei Zahlen in einem Satz von drei Zahlen findet. So 5 Beispiele:Finden Sie den nächsten Durchschnitt von drei Zahlen - Code-Optimierung

x1 <- c(1,5,7) 
x2 <- c(NA,2,3) 
x3 <- c(2,6,4) 
x4 <- c(1,NA,NA) 
x5 <- c(1,3,1) 

würde ich jeweils eine Leistung von

y1 = 6 
y2 = 2.5 
y3 = 4 
y4 = 1 
y5 = 1 

bekommen. Im Grunde, die nächsten 2 Zahlen zu finden, dann sie zu mitteln, NA und Verbindungen betreffend.

Dieser Code ist eine Ungeheuerlichkeit:

x <-x[!is.na(x)] 
x <-x[order(x)] 
y <-ifelse(length(x) == 1, x, 
     ifelse(length(x) == 2, mean(x), 
     ifelse(length(x) == 3, 
      ifelse(abs(x[1] - x[2]) == abs(x[2] - x[3]), mean(x), 
      ifelse(abs(x[1] - x[2]) > abs(x[2] - x[3]), mean(x[2:3]), 
       ifelse(abs(x[1] - x[2]) < abs(x[2] - x[3]), mean(x[1:2]), 
    "error"))), NA))) 

Es funktioniert, aber da dies Teil einer größeren for Schleife ist, ich habe mich gefragt, gibt es einen besseren Weg, dies zu tun ..

Antwort

4

Wir sind ein definieren S3 generisch mit "list" und "default" Methoden.

Die Methode "default" nimmt einen Vektor und sortiert ihn (wodurch auch die NA-Werte entfernt werden). Wenn dann die verbleibende Länge < = 1 ist, wird der einzelne Wert oder NA zurückgegeben, wenn keine vorhanden ist. Wenn die Länge 2 ist oder die zwei aufeinanderfolgenden Differenzen gleich sind, wird der Mittelwert aller Werte zurückgegeben. Andernfalls findet es den Index des ersten des Paares der nächsten zwei Werte und gibt den Mittelwert der Werte zurück.

Die Methode "list" wendet die Standardmethode wiederholt an.

mean_min_diff <- function(x) UseMethod("mean_min_diff") 

mean_min_diff.list <- function(x) sapply(x, mean_min_diff.default) 

mean_min_diff.default <- function(x) { 
    x0 <- sort(x) 
    if (length(x0) <= 1) c(x0, NA)[1] 
    else if (length(x0) == 2 || sd(diff(x0)) == 0) mean(x0) 
    else mean(x0[seq(which.min(diff(x0)), length = 2)]) 
} 

Jetzt ist es testen:

mean_min_diff(x1) 
## [1] 6 

mean_min_diff(list(x1, x2, x3, x4, x5)) 
## [1] 6.0 2.5 4.0 1.0 1.0 
+0

funktioniert nicht für 'x3 <- c (2,6,4)' – rbm

+1

ja, aber das ist nicht das, was das Tun des OP: 'abs (x [1] - x [2]) == abs (x [2] - x [3]), mittel (x) ' – rbm

+0

OK. Habe überarbeitet. –

Verwandte Themen