2017-09-22 11 views
1

Meine Frage ist fast identisch mit this one, außer, den nächstliegenden Wert zwischen einem Spaltenwert und einer festen Zahl zu finden, z. "2", ich möchte den nächsten Wert zu dem Wert in einer anderen Spalte finden.. Hier ist ein Beispiel von Daten:Rückgabewert basierend auf dem Finden des nächstliegenden Wertes zwischen anderen zwei Spalten in df

df <- data.frame(site_no=c("01010500", "01010500", "01010500","02010500", "02010500", "02010500", "03010500", "03010500", "03010500"), 
        OBS=c(423.9969, 423.9969, 423.9969, 123, 123, 123, 150,150,150), 
        MOD=c(380,400,360,150,155,135,170,180,140), 
        HT=c(14,12,15,3,8,19,12,23,10)) 

die wie folgt aussieht:

site_no  OBS MOD HT 
1 01010500 423.9969 380 14 
2 01010500 423.9969 400 12 
3 01010500 423.9969 360 15 
4 02010500 123.0000 150 3 
5 02010500 123.0000 155 8 
6 02010500 123.0000 135 19 
7 03010500 150.0000 170 12 
8 03010500 150.0000 180 23 
9 03010500 150.0000 140 10 

Das Ziel ist, für jeden „site_no“, die am nächsten MOD Wert finden, der den OBS-Wert übereinstimmt, dann kehrt die entsprechende HT. Beispiel: Für site_no 01010500 ergibt 423.9969 - 400 die minimale Differenz, und die Funktion würde also 12 zurückgeben. Ich habe die meisten Lösungen aus dem anderen Post versucht, aber einen Fehler wegen $ mit atomischem Vektor erhalten (der df ist rekursiv) , aber ich denke, die Funktion ist nicht). Ich habe versucht:

ddply(df, .(site_no), function(z) { 
    z[abs(z$OBS - z$MOD) == min(abs(z$OBS - z$MOD)), ] 
}) 
Error in z$River_Width..m. - z$chan_width : 
    non-numeric argument to binary operator 
+0

Vielleicht 'Bibliothek (dplyr); df%>% group_by (site_no)%>% slice (which.min (HT)) 'oder kann' df%>% group_by (site_no)%>% slice sein (which.min (abs (OBS-MOD))) ' – akrun

+0

@akrun, die 2. Option funktioniert super. Ich kann es als eine Antwort akzeptieren, wenn Sie als eins einreichen. Einzige Frage: Die zurückgegebene str ist ein tibble, und einige Combo tbl von Datenframes .. könnte ich dieses Ergebnis in einem einzigen Datenrahmen bekommen? – LauraR

+0

Danke. Ich fügte meinen Kommentar als eine Lösung mit einer Erklärung hinzu. Sie können in data.frame konvertieren, wenn Sie es wollen – akrun

Antwort

0

Nach Gruppierung von 'site_no', slice wir die Zeilen, die die minimale absolute Differenz zwischen dem 'OBS' hat und

library(dplyr) 
res <- df %>% 
     group_by(site_no) %>% 
     slice(which.min(abs(OBS-MOD))) 

HINWEIS 'MOD': Durch dplyr verwenden, einige Zusätzliche Klassen wie tbl_dftibble usw. werden hinzugefügt, die mit den meisten anderen Funktionen funktionieren sollten. Wenn es irgendein Problem gibt, können wir es data.frame konvertieren mit as.data.frame

str(res %>% 
     as.data.frame) 
#'data.frame': 3 obs. of 4 variables: 
#$ site_no: Factor w/ 3 levels "01010500","02010500",..: 1 2 3 
#$ OBS : num 424 123 150 
#$ MOD : num 400 135 140 
#$ HT  : num 12 19 10 
+0

Ich habe ein kleines Problem mit diesem .. Wenn es eine Krawatte gibt, gibt der Operator den ersten Wert im Index zurück. Im Idealfall möchte ich das Maximum (HT) zurückgeben. Kann das nicht mit der Verwendung von Slice arbeiten .. versuchte, Filter und Rang zu verschieben, aber kein Glück. – LauraR

+0

@LauraR In diesem Fall, 'df%>% group_by (site_no)%>% ordnen (site_no, desc (HT))%>% slice (which.min (abs (OBS-MOD)))' Sie können das überprüfen nach Änderung von 'df $ MOD [5] <- 135' – akrun

Verwandte Themen