WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Selektive Matrixauslese

 

McFly1984
Forum-Anfänger

Forum-Anfänger


Beiträge: 16
Anmeldedatum: 02.06.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 04.06.2015, 13:34     Titel: Selektive Matrixauslese
  Antworten mit Zitat      
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',[1 1 1],[331 181 744]);
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);


Wie würdet Ihr die Selektion lösen?
Es muss doch eine elegantere Lösung geben als das ganze so zu verschachteln oder?

Besten Dank

MfG Marcus
Private Nachricht senden Benutzer-Profile anzeigen


Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 04.06.2015, 16:26     Titel: Re: Selektive Matrixauslese
  Antworten mit Zitat      
Hallo McFly1984,

Herzlich willkommen im Forum!

Zitat:
Für alle Messwerte möchte ich eine Rechenoperation durchführen und das Ergebnis in eine neue Matrix mit der Größe 331x181x1 schreiben.

In Matlab sind prinzipiell [331 x 181 x 1] Arrays genau das gleiche wie [331 x 181] Matrizen, weil abschließende singuläre Dimensionen verschwinden.

Zitat:
Die Werte mit -9 sollen erhalten bleiben und so in der neuen Matrix eingetragen werden.

Davon ist in Deinem Code nichts zu finden.
Zitat:
Code:
if Hs(AA,BB,CC)==-9;
Hs(AA,BB,CC)=-9;

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.

Zitat:
Code:
if Hs(:,:,:)==-9;
Hs(:,:,:)=-9;

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.

Zitat:
Code:
if Hs(AA,BB,CC)==-9;
Hs(AA,BB,CC)=-9;

Dies ändert nachwievor die -9 Elemente in den Wert -9, kann also genauso gut weggelassen werden.

Code:
[quote]    E05JAN(:,:,1)=(sum((Hs>=0.5),3)/a);[/quote]

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:
Code:
sum((Hs(AA, BB, :)>=0.5))/a

Aber was soll mit den -9 Elementen dann geschehen? Gehen die in die Summe mit ein? Was ist "a"?

Das "clear AA, BB, CC" kannst Du weglassen, da dies in Matlab eher Zeitverschwendung ist und im besten Fall keine Zeit raubt.

Ich vermute, Du suchst nach etwas wie:
Code:
HS(HS == -9) = NaN;
E05JAN = nanmean(HS, 3);

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
McFly1984
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 16
Anmeldedatum: 02.06.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 04.06.2015, 19:33     Titel:
  Antworten mit Zitat      
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.

Code:
E05JAN(:,:,1)=(sum((Hs>=0.5),3)/a);

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.
Private Nachricht senden Benutzer-Profile anzeigen
 
Winkow
Moderator

Moderator



Beiträge: 3.842
Anmeldedatum: 04.11.11
Wohnort: Dresden
Version: R2014a 2015a
     Beitrag Verfasst am: 04.06.2015, 20:23     Titel:
  Antworten mit Zitat      
Zitat:
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.

Code:
E05JAN=(sum((Hs>=0.5)&Hs~=-9,3)/a);

meinst du sowas?
_________________

richtig Fragen
Private Nachricht senden Benutzer-Profile anzeigen
 
McFly1984
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 16
Anmeldedatum: 02.06.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.06.2015, 13:39     Titel:
  Antworten mit Zitat      
Hallo,
also ich hab mir nochmal folgende Abfrage angesehen

Code:
E05JAN(:,:,1)=(sum((Hs>2),3)/a);


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.

Zu Deiner Codezeile:
Code:
E05JAN=(sum((Hs>=0.5)&Hs~=-9,3)/a);

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.

Gruß Marcus
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 06.06.2015, 15:37     Titel:
  Antworten mit Zitat      
Hallo McFly1984,

Zitat:
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);

Das ist nun der Mittelwert über alle Elemente, die nicht -9 sind. Vielleicht suchst Du aber auch:
Code:
Y = sum(X, Dim) ./ size(X, 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
Private Nachricht senden Benutzer-Profile anzeigen
 
McFly1984
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 16
Anmeldedatum: 02.06.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 11.06.2015, 14:21     Titel:
  Antworten mit Zitat      
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.

Code:
%JANUAR
%Mittelwert
Hs = ncread(['SOHIP-V4-',y,'.nc'],'hsign',[1 1 1],[331 181 744]);
a=length(Hs);

counter=1;

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(:,:,z)=(sum((Hs>=0.5),3)/a);

end;
counter=counter+1
end;
end;
end;


Die Arrays für die Ergebniswerte habe ich vorher schon angelegt

Code:
%Preallocation der Arrays für die errechneten Werte
E05JAN(1:331,1:181,1:52)=-9;

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.

MfG Marcus
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 13.06.2015, 01:10     Titel:
  Antworten mit Zitat      
Hallo McFly1984,

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
Private Nachricht senden Benutzer-Profile anzeigen
 
McFly1984
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 16
Anmeldedatum: 02.06.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 24.06.2015, 13:25     Titel:
  Antworten mit Zitat      
Hallo Jan,
hier ein kleines Matrixbeispiel

val(:,:,1) =

-9.0000 0.2000 1.2000
-9.0000 0.6000 1.5000
-9.0000 0.9000 1.1000


val(:,:,2) =

-9.0000 0.3000 1.2000
-9.0000 0.7000 1.1000
-9.0000 0.9000 1.5000

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)

Mein Wunschergebnis sieht folgendermaßen aus
-9 0 1
-9 1 1
-9 1 1

Ich will in der Ergebnismatrix die Messwerte immer noch von den Randwerten unterscheiden können.

Wie löse ich das am besten?

Danke Marcus
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 25.06.2015, 15:34     Titel:
  Antworten mit Zitat      
Hallo McFly1984,
Code:
Result = mean(val > 0.5, 3);
Result(any(val < 0, 3)) = -9;

Hilft das?

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

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
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

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.