Moin moin,
ich habe ein Selektionsproblem in einer großen Matrix.
Die Matrix besteht aus 331x181x744 Werten.
In der Matrix stehen Messwerte >0 und Werte mit -9.
Für alle Messwerte möchte ich eine Rechenoperation durchführen und das Ergebnis in eine neue Matrix mit der Größe 331x181x1 schreiben. Die Werte mit -9 sollen erhalten bleiben und so in der neuen Matrix eingetragen werden. Genauer gesagt ist es mir total egal was in den -9 Feldern steht, solange der Wert inhaltlich klar von den Ergebnissen der Rechenoperation zu unterscheiden ist, diese liegen zwischen 0 und 1.
Ich wollte das ganze mit einer if Abfrage lösen:
Code:
Hs = ncread(['SOHIP-V4-',y,'.nc'],'hsign',[111],[331181744]);
a=length(Hs);
if Hs(:,:,:)==-9;
Hs(:,:,:)=-9;
else
E05JAN(:,:,1)=(sum((Hs>=0.5),3)/a);
ncwrite('Ergebnis.nc','E05JAN',E05JAN);
Das funktioniert zwar vom Funktionsablauf, aber das Ergebnis ist falsch, die Felder mit -9 werden nicht erkannt.
Wenn ich jedes Feld einzeln über eine for-Schleife anspreche komme ich zum richtigen Ergebnis, aber die Berechnungszeit vergrößert sich extrem (kein Wunder es sind dann auch knapp 45 Mio Schleifendurchläufe).
Code:
for AA=1:331;
for BB=1:181;
for CC = 1:744;
if Hs(AA,BB,CC)==-9;
Hs(AA,BB,CC)=-9;
else
E05JAN(:,:,1)=(sum((Hs>=0.5),3)/a);
end;
end;
end;
end;
clear AA BB CC;
ncwrite('Ergebnis.nc','E05JAN',E05JAN);
Das ersetzt Elemente mit dem Wert -9 im Input-Array durch -9, also kann man das auch einfach weglassen. Jedenfalls landet es nicht im Output-Array. Es ist auch nicht klar, wie die Position der -9 im [331 x 181 x 744] Array genau im [331 x 181] Array erhalten bleiben soll.
Das ist ein häufiger Fehler von Programmier-Anfängern: Die IF-Abfrage benötigt eine skalare Bedingung. Es wird deshalb implizit ein ALL() eingefügt, denn wie sollte bei einem Array voller TRUE und FALSE-Werte aus der IF-Bedingung magisch in "Hs(:,:,:)=-9" bekannt sein, welcher Elemente auf -9 gesetzt werden sollen? "Hs(:,:,:)=-9" bedeutet ja, das alle Elemente auf -9 gesetzt werden sollen.
Zitat:
Wenn ich jedes Feld einzeln über eine for-Schleife anspreche komme ich zum richtigen Ergebnis, aber die Berechnungszeit vergrößert sich extrem (kein Wunder es sind dann auch knapp 45 Mio Schleifendurchläufe).
Wenn es "kein Wunder" ist, was ist dann genau Deine Frage? Wie groß ist genau "extrem"? Geht es um Millisekunden oder Minuten?
Es ist immer noch nicht genau klar, was das Programm berechnen soll, sodass eine sinnvolle Antwort nicht wirklich möglich ist.
Hier hängt der Ausdruck auf der rechten Seite gar nicht von den Schleifen ab und Es werden jeweils alle Elemente im Array E05JAN auf den gleichen Wert gesetzt. Das dabei die Elemte immer wieder mit neuen Werten überschrieben werden ist bestimmt nicht gewollt. Aber was genau ist gewollt?
Ich rate mal dass Du statt "sum((Hs>=0.5),3)/a" dies meinst:
Moin Jan,
Danke für die ausführliche Antwort.
Vielleicht nochmal eine kurze Erklärung was ich machen will.
Ich habe Messwerte im Stundentakt für einen gesamten Monat (24h x 31d = 744). Ich möchte Eintrittshäufigkeiten für bestimmte Ereignisse berechnen. z.B. alle Messwerte größer 0.5, dafür summiere ich die Anzahl dieser Ereignisse und teile sie durch die Anzahl a (zweite code Zeile a=length(Hs))
Dadurch erhalte ich als Ergebnis nur 1 z Ebene
In der Tat könnte ich die if Hs(AA,BB,CC)==-9 weglassen, aber wie kann ich es denn formulieren, dass bei der Bedingung -9 nichts mit den Inhalten geschehen soll?
Die Schleife war nach 1 Stunde noch nicht durchgelaufen. Aber vielleicht liegt es daran, das ich mich irgendwo festgefahren habe. Ich habe keinen Zähler eingebaut gehabt und somit weiß ich nicht wie weit wir waren. Da ich das ganze aber für 12 Monat und 52 Jahre berechnen will, kommt da einiges an Rechenzeit zusammen.
Ich war bisher der Meinung, das dieser Befehl dazu führt, dass die Eintrittshäufigkeit für die Ereignisse >0.5 ermittelt wird (über alle 744 Z Werte) und diese eine Eintrittshäufigkeit dann in einer z Eben abgelegt wird. Ist dem nicht so?
nanmean geht bei mir nicht, da ich die Statistics and Machine Learning Toolbox nicht habe.
Ich habe Messwerte im Stundentakt für einen gesamten Monat (24h x 31d = 744). Ich möchte Eintrittshäufigkeiten für bestimmte Ereignisse berechnen. z.B. alle Messwerte größer 0.5, dafür summiere ich die Anzahl dieser Ereignisse und teile sie durch die Anzahl a (zweite code Zeile a=length(Hs))
was passiert wenn du nicht 31 tage hast sodern zb nur 10? length ist da nicht wirklich die richtige wahl.
Wenn ich diese Abfrage auf folgende Matrix anwende (in diesem Falle ist a=3):
val(:,:,1) =
1 2 3
4 5 6
val(:,:,2) =
7 8 9
10 11 12
val(:,:,3) =
13 14 15
16 17 18
Lautet das Ergebnis:
0,67 0,67 1
1 1 1
Die Abfrage macht also meines Erachtens das was ich von ihr erwarte: errechnet die Eintrittshäufigkeit über alle z - Ebenen und schreibt diese in ein neues Array.
@ Jan habe ich etwas übersehen?
@ Winkow, die Monate werden einzeln eingelesen und da habe ich die Anzahl der Z-Ebenen an die Monate angepasst. Glücklicherweise haben die Monate über die Jahre die selbe Länge und das von Dir erwähnte Problem tritt nicht auf.
Die Zeile is ganz nett, sie ignoriert bestimmte Werte in der Berechnung, aber leider ist das noch nicht das was ich brauche. Denn da die -9 auf allen Z Ebenen an den gleichen Stellen steht, führt das dazu, das in den relevanten Feldern eine 0 rauskommen würde, da keine Elemente vorhanden sind, welche die Abfragebedingung erfüllen.
Das Problem ist aber, dass es auch Messwerte gibt, die diese Bedingung nicht erfüllen und daher im Ergebnis auch 0 rauskommt. Und an genau dieser Stelle kann ich dann den Messwert nicht mehr vom Randwert unterscheiden.
In der Ergebnismatrix mit nur einer z-Ebene soll dort wo bei den Ausgangsdaten eine -9 steht immernoch ein -9 stehen.
Vorschläge?
Ich werde mir meine Schleife nochmal genauer ansehen und einen Zähler einbauen um zu gucken ob er sich festläuft oder es nur wirklich wirklich lange dauert.
Ich habe Messwerte im Stundentakt für einen gesamten Monat (24h x 31d = 744). Ich möchte Eintrittshäufigkeiten für bestimmte Ereignisse berechnen. z.B. alle Messwerte größer 0.5, dafür summiere ich die Anzahl dieser Ereignisse und teile sie durch die Anzahl a (zweite code Zeile a=length(Hs))
Dadurch erhalte ich als Ergebnis nur 1 z Ebene
Während das für Dich bestimmt klar ist, verstehe ich es nicht, weil ich mit dem Problem gar nicht vertraut bin. Die Bedeutung der Zahlen ist für die Lösung egal. Es könnte also schlicht eine Zufalls-Matrix sein.
"a=length(HS)" ist nicht hilfreich, oder? Kommt es wirklich auf die längste Dimension von HS an?
Was genau mathematische berechnet werden soll, ist immer noch nicht klar.
NANMEAN lässt sich mit wenigen Zeilen nachprogrammieren und das wurde imNetz bereits sehr häufig diskutiert. Den Umweg über die NaNs kannst Du Dir dann auch sparen, weil -9 ja bereits eindeutig ist:
Code:
function Y = NineMean(X, Dim)
Match = (X == - 9);
X(Match) = 0;
Y = sum(X, Dim) ./ sum(~Match, Dim);
Wenn Du für so kleine Probleme Laufzeiten mit mehr als 1 sek bekommst, läuft etwas schief. Benutze den Debugger und/oder den Profile um zu suchen, wo was nicht wie gewünscht läuft.
Zitat:
In der Tat könnte ich die if Hs(AA,BB,CC)==-9 weglassen, aber wie kann ich es denn formulieren, dass bei der Bedingung -9 nichts mit den Inhalten geschehen soll?
Huch? Um zu programmieren, dass nichts geschehen soll, reicht es, nichts zu programmieren. Du möchtest wohl einfach "if Hs(AA,BB,CC) ~= -9" berücksichtigen?
Genau das macht die obige Funktion NineMean auch, nur halt mit logischer Indizierung.
Gruß, Jan
Zuletzt bearbeitet von Jan S am 25.06.2015, 15:18, insgesamt einmal bearbeitet
Hallo Jan,
danke für die Tips, ich werde es heute abend mal ausprobieren.
Ich hab mir die Schleife im Debugger angesehen. Das Problem ist, die Schleifendurchläufe dauern immer länger.
Am Anfang läuft die Schleife sehr schnell, die ersten 1 Million Durchläufe sind in weniger als 30 Sekunden durch, doch es wird immer langsamer. Bis zur zweiten Million dauert es dann schon ganze 5 Minuten.
Nich wundern z 1:52 steht deshalb dort, weil ich insgesamt 52 Jahre habe die einzeln eingelesen werden müssen und die Ergebnisse für die 52 Jahre schreibe ich auch einzeln um sie anschließend zusammenzufassen.
Woran kann es liegen das die Berechnung immer langsamer wird? Eigentlich gibt es doch da nichts was voll laufen kann oder habe ich etwas übersehen?
Zitat:
Was genau mathematische berechnet werden soll, ist immer noch nicht klar.
Ich will Eintrittshäufigkeiten für bestimmte Ereignisse berechnen. Also lege ich einen Schwellenwert fest z.B. >0.5 summiere alle Ergebnisse und teile diese durch die Anzahl der Werte (dafür auch length(a)).
In der Ergebnismatrix sollen diese Werte dann stehen und an der Stelle, an der keine Messwerte standen sondern -9, soll ein Wert stehen, den ich von den berechneten Werten klar unterscheiden kann also <0 oder >1, denn das ist der Wertebereich, der von den Messwerten durch die Berechnung der Eintrittshäufigkeiten belegt ist.
Dein Code enthält immer noch das vollkommen sinnfreie Überschreiben der elemte mit dem Wert -9 mit dem neuen Wert -9. Das ist einfach nicht sinnvoll und ich rate Dir dringend dazu, das zu entfernen, weil es außer Verwirrung nichts bringt.
Die Bedeutung dieser Zeile bleibt mir auch verborgen:
Zitat:
E05JAN(:,:,z)=(sum((Hs>=0.5),3)/a);
Was ist "z"? Wieso werden hier 3 Schleifen ausgeführt und dann doch immer nur der gleicher Werte berechnet? Die rechte Seite dieser Zeile hängt ja gar nich von den Schleifen ab!
Zitat:
Woran kann es liegen das die Berechnung immer langsamer wird? Eigentlich gibt es doch da nichts was voll laufen kann oder habe ich etwas übersehen?
Doch, Du hast da sicherlich etwas übersehen. Gibt es vielleicht eine MLint-Warnung im Code?
Solange wir nicht den vollständigen Code sehen, können wir nicht erraten, was genau geschieht. Aber der Profiler kann herausfinden, wo Laufzeit verwendet wird.
Zitat:
Ich will Eintrittshäufigkeiten für bestimmte Ereignisse berechnen. Also lege ich einen Schwellenwert fest z.B. >0.5 summiere alle Ergebnisse und teile diese durch die Anzahl der Werte (dafür auch length(a)).
Für die Eintrittshäufigkeit spielen die -9-Werte also keine Rolle? In der Summe werden sie ja nicht ausgeschlossen.
Zitat:
In der Ergebnismatrix sollen diese Werte dann stehen und an der Stelle, an der keine Messwerte standen sondern -9, soll ein Wert stehen, den ich von den berechneten Werten klar unterscheiden kann also <0 oder >1, denn das ist der Wertebereich, der von den Messwerten durch die Berechnung der Eintrittshäufigkeiten belegt ist.
Diesen Satz verstehe ich nicht. Wie können in der Ergebnismatrix Werte "gestanden" haben? Wo genau sollen die invaliden Werte berücksichtigt werden? Kannst Du ein Beispiel mit einer kleinen Matrix angeben?
Gruß, Jan
Zuletzt bearbeitet von Jan S am 25.06.2015, 15:11, insgesamt einmal bearbeitet
Nun möchte ich Eintrittshäufigkeiten über alle z Ebenen für alle Ereignisse >0.5 berechnen und diese in eine neue Ergebnismatrix schreiben.
Rein mathematisch wird das Ergebnis folgendermaßen aussehen:
0 0 1
0 1 1
0 1 1
Problematisch ist an dieser Stelle das zweite Feld in der ersten Zeile der Ergebnismatrix. Hier wurde die Bedingung durch die Messwerte nicht erfüllt und somit wird eine null errechnet, dies passiert auch für die Werte aus der ersten Spalte welche aber keine Messwerte sind, sondern Randwerte. Daher kann ich nun nicht mehr unterscheiden ob es sich bei den 0 Werten in der Ergebnismatrix um Messwerte handelt (>0) oder um Randwerte (-9)
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.