Koordinatenabgleich - effizienter Weg

Wie rufe ich R-Funktionen auf, wie selektiere ich Daten, ich weiß nicht genau ....

Moderatoren: EDi, jogo

Antworten
jessi
Beiträge: 90
Registriert: Mo Jul 10, 2017 9:23 am

Koordinatenabgleich - effizienter Weg

Beitrag von jessi » Mo Sep 09, 2019 9:58 am

Hallo Liebes R-Forum,

ich hatte letzte Woche schon einmal ein paar Code-Zeilen geschrieben (Betreff: Messdaten auf Rasterfile interpolieren). Den Ansatz habe ich jetzt verworfen und ich konzentrierte mich auf das Vergleichen der Messwerte mit dem nächstgelegenen Modellwert.

Ich schildere kurz das "Problem". Ich habe ein data.frame mit Messwerten (long, lat, Messwert, Station, ...) und ein modelliertes Dichte-Feld. Den Messwert und den Modellwert möchte ich jetzt miteinander vergleichen. Dazu habe ich mir den zur Station nächstgelegenen Gitterpunkt gesucht und die Werte einander zugeordnet. Soweit so gut. Allerdings habe ich das jetzt mal nur für einen Tag gemacht, ich habe den Messdatensatz mit subset so eingegrenzt, dass nur Werte mit der jeweiligen Bedingung in die Zuordnung eingingen. Ich habe aber Messwerte (Tagesmittelwerte) von insgesamt vier Monaten, also etwa 120 Tage/Werte. Mein Plan wäre, da ja der Modellwert unabhängig vom Tag ist, und somit am Gitterpunkt immer den gleichen Wert hat, einen Plot/Zeitreihe zu erstellen, wie die tatsächlichen Messwerte um den Modellgitterpunkt variieren. Dazu benötige ich natürlich alle Tagesmittelwerte.

Mein Problem ist jetzt, dass , wenn ich alle Messwerte zulasse (also keine Eingrenzung mehr auf einen Tag), der Durchlauf der Schleife ewig dauert.

Ich zeige euch meinen Code(Ansatz), vermutlich nicht besonders elegant ... :shock:

Code: Alles auswählen

library(sp)
library(raster) 

s <- read.csv("test_r_for.csv", header = TRUE, sep = ";", dec = ",") 
## vorerst Einschränkung auf einen Tag 
s_at <- subset(s, s$Tag == 15 & s$Monat == 3)
station <- data.frame(s_at$Laenge, s_at$Breite, s_at$Tagesmittel)
colnames(station) <- c("longitude", "latitude", "Mittel") 

r <- raster("dichte.tif")
r_coord <- rasterToPoints(r)
r_coord_df <- as.data.frame(r_coord) 
colnames(r_coord_df) <- c("longitude", "latitude", "Dichte")

## wandle die Input-Koordinaten in SpatialPointsDataFrames um 
coordinates(station) <- c("longitude", "latitude")
coordinates(r_coord_df) <- c("longitude", "latitude")

closestSiteVec <- vector(mode = "numeric",length = nrow(station))
minDistVec     <- vector(mode = "numeric",length = nrow(station))

for (i in 1 : nrow(station))
   {
      distVec <- spDistsN1(r_coord_df,station[i,],longlat = TRUE)
      minDistVec[i] <- min(distVec)
      closestSiteVec[i] <- which.min(distVec)
   }

dichte_modell <- as(r_coord_df[closestSiteVec,]$Dichte,"numeric")

df_zuordnung_messung_modell = data.frame(coordinates(station),station$Mittel,
                                    closestSiteVec,round(minDistVec,4),dichte_modell)


colnames(df_zuordnung_messung_modell) <- c("Laenge", "Breite", "Mittelwert", "Index_nächster_GP", "Entfernung", "Dichte_Modell") 

Für einen ausgewählten Tag funktioniert die Schleife perfekt, allerdings wenn ich den Vektor erweitere nicht mehr, da die Schleife ja dann mehrere hundert mal durchlaufen muss.

Gibt es hier eine Möglichkeit, den Code zu beschleunigen, oder muss ich die Zeit einfach abwarten?

Danke schon einmal für eure Hilfe.

Grüße
Jess
Dateianhänge
test_r_for.csv
(36.35 KiB) 2-mal heruntergeladen

bigben
Beiträge: 1065
Registriert: Mi Okt 12, 2016 9:09 am

Re: Koordinatenabgleich - effizienter Weg

Beitrag von bigben » Mo Sep 09, 2019 10:15 am

Hallo Jess,

bei spatial statistics kann ich leider nicht mitreden, inhaltlich also nicht ganz soviel beisteuern. Auf der Code-Ebene scheinen die Aufgaben der Schleife gut parallelisierbar. Wenn Dein Rechner 4 Kerne hat, könnte einer das erste Viertel aller i-Werte, einer das zweite Viertel aller i-Werte und einer das dritte und einer das vierte Viertel Deiner i-Werte berechnen. Bei acht Kernen umso besser. Mithilfe des foreach-package kannst Du das programmieren, ohne von der for-Schleife wegzugehen, mit der Du ja schon umgehen kannst. Ich weiß nicht, wie groß Dein Laufzeitproblem ist. Würde eine doppelte Durchlaufgeschwindigkeit da schon helfen?

In der Schleife werden sowohl min als auch which.min den ganzen Vector durchlaufen und beide nach dem gleichen suchen, nämlich nach dem kleinsten Wert. Wenn Du nur which.min den Vektor durchsuchen lässt, kannst Du mit diesem Ergebnis nachher ganz einfach auf das Minimum direkt zugreifen.

Code: Alles auswählen

bsp <- runif(100)
index <- which.min(bsp)
bsp[index] == min(bsp)
Das wird aber nur bei sehr großen Vektoren oder bei sehr, sehr häufigem Durchlaufen spürbar werden.

Letztlich ist es leider so, dass for-Schleifen in R meistens nicht wirklich schnell werden. Wenn man sie durch apply und seine Verwandten ersetzt, entsteht ganz leicht ein Geschwindigkeitsvorteil, der sehr viel erheblicher als die beiden oben genannten ist. Erfordert dann halt ein Umstellen des Denkens und der Progammiertechnik.

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte

Athomas
Beiträge: 248
Registriert: Mo Feb 26, 2018 8:19 pm

Re: Koordinatenabgleich - effizienter Weg

Beitrag von Athomas » Mo Sep 09, 2019 11:16 am

Ich verstehe Dein Problem nicht – Du hast viele Messstationen und für jede von ihnen viele Messwerte (Tagesmittel). Zu jeder Messstation hast Du den nächstgelegenen Rasterpunkt und dessen zugehörigen Modellwert, der nicht zeitlich variiert – ich nehme an, in einer separaten Datei.

Was hindert Dich daran, die Modellwerte an die Messwerte-Daten dranzumergen und dann die Stationen, die Dich interessieren, auszuwerten?
Wenn Du dazu das Package data.table verwendest, bekommst Du das Ergebnis quasi auf Knopfdruck…

P.S.: Da man in R wunderbar mit Datumswerten hantieren kann, ist die Aufspaltung des Datums (wenn es denn mal als Ganzes vorhanden war) in Tag und Monat keine gute Idee!

jessi
Beiträge: 90
Registriert: Mo Jul 10, 2017 9:23 am

Re: Koordinatenabgleich - effizienter Weg

Beitrag von jessi » Mo Sep 09, 2019 12:54 pm

Hallo Athomas,

die Modellwerte und die Messwerte mergen kann ich doch nur, wenn die Koordinaten übereinstimmen? Die nächstgelegenen Rasterpunkt zum Messwert bestimme ich mit der for-Schleife. Oder stehe ich hier nur irgendwie auf der Leitung :?:

Grüße
Jessi

Athomas
Beiträge: 248
Registriert: Mo Feb 26, 2018 8:19 pm

Re: Koordinatenabgleich - effizienter Weg

Beitrag von Athomas » Mo Sep 09, 2019 1:05 pm

Aber Du kannst Dir doch die Koordinaten der Messstation zusammen mit dem nächstgelegenen Rasterpunkt und dessen Modellwert merken - und das Ganze über die Koordinaten wieder zurückspielen!?

jessi
Beiträge: 90
Registriert: Mo Jul 10, 2017 9:23 am

Re: Koordinatenabgleich - effizienter Weg

Beitrag von jessi » Mo Sep 09, 2019 3:49 pm

Aber wie komme ich ohne die Schleife zum nächstgelegenen Rasterpunkt :?: - ich checke es gerade gar nicht.

Athomas
Beiträge: 248
Registriert: Mo Feb 26, 2018 8:19 pm

Re: Koordinatenabgleich - effizienter Weg

Beitrag von Athomas » Mo Sep 09, 2019 4:16 pm

ich checke es gerade gar nicht.
Vielleicht bin ich ja auch auf dem falschen Dampfer :) ? Ich habe mich mich mit "spatial data" bisher nur am Rande beschäftigt...

In meinen Augen ist es ein völlig isoliertes Problem, einer Gruppe von Koordinaten (Messstationen) den jeweils nächstgelegenen Rasterpunkt zuzuordnen - und dafür scheint es - jedenfalls wenn ich "r nearest raster point" google - einige Fertiglösungen zu geben, zum Beispiel die Funktion nearest.raster.point aus dem Package spatstat.

Wenn Dein Problem hier liegt - gibt es etwas, was gegen die Verwendung dieser vorhandenen Funktionen spricht?

Benutzeravatar
EDi
Beiträge: 888
Registriert: Sa Okt 08, 2016 3:39 pm

Re: Koordinatenabgleich - effizienter Weg

Beitrag von EDi » Di Sep 10, 2019 6:37 pm

wenn ich alle Messwerte zulasse (also keine Eingrenzung mehr auf einen Tag), der Durchlauf der Schleife ewig dauert.
Sind die Stationen nicht stabil über die Tage? Muss man ja nur einmal machen...

Und wieso überhaupt über die Distanz gehen? Verstehe ich nicht...

Aus einem raster (auch ein rasterstack) kann man mit raster::extract die rasterwerte an bestimmten Koordinaten rausziehen. Das ist auch recht performant...

Danach einfach nur ein Join über die stationsId mit den messdaten. Die aggregation ist dann kein problem mehr...
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.

Antworten