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

NaN-Werte interpolieren

 

klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 31.07.2012, 12:25     Titel: NaN-Werte interpolieren
  Antworten mit Zitat      
Hallo,

zunächst: ich habe schon die Suchfunktion genutzt, aber keine Lösung für mein Problem gefunden.

Ich habe eine Matrix mit 26x84096 Messwerten. Nun sind einige Messwerte fehlerhaft und mit NaN eingetragen. Diese will ich nun, am besten linear, interpolieren jedoch nur, wenn nicht mehr als 6 Werte hintereinander fehlerhaft sind. ( In der Matrix sind teilweise > 3000 Werte in folge fehlerhaft)

Ich habe das mit der Funktion interpol1 versucht, habe nun aber folgende Probleme:

1. Funktioniert leider nur die kubische Interpolation, da Matlab sonst nicht mit den NaN-Werten umgehen kann. Kann ich das irgendwie so programmieren,dass ich auch die lineare Interpolation nehmen kann?

2. Weiss ich nicht genau, wie ich programmieren kann, dass er nur interpoliert, falls nicht mehr als 6 Werte in Folge fehlerhaft sind. (Da sonst unsinnige Werte rauskommen)
Bis jetzt habe ich es mit einer Schleife versucht, allerdings dauert das ewig....

Hier mein Code:
[code
]l = 1;
for i = 1:14016
Y = Matrix(1,Smile;
X = 1:length(Matrix(1,Smile);
Matrixi(l:l+12) = interp1(X,Y,l:1:l+12,'pchip','extrap');
l = l + 12;
end
[/code]


außerdem gibt Matlab immer die Warnung::

Warning: All data points with NaN in their value will be ignored.
> In polyfun/private/chckxy at 103
In pchip at 59
In interp1 at 283
In test at 12

aus. Da allerdings die Interpolation funktioniert scheint das nicht so schlimm zu sein, oder?

Ich hoffe ihr könnt mir helfen, vielen Dank im vorraus schonmal.

Gruß


klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 31.07.2012, 13:12     Titel:
  Antworten mit Zitat      
edit:

okay hier mal ein Code wie es bei mir funtioniert. Allerdings braucht mein Matlab dafür >12 Minuten Sad

es würde mit reshape bestimmt viel schneller gehen, allerdings habe ich keine Idee wie ich das damit programmieren könnte.

Code:

l = 0
Y = Matrix(1,:);
X = 1:length(Matrix(1,:));
for i = 1:14016
if sum(isnan(Matrix(1,l+1:l+7))) < 7;
Matrixi(1,l+1:l+6) = interp1(X,Y,l+1:1:l+6,'pchip','extrap');

else Matrixi(1,l+1:l+6) = Matrix(1,l+1:l+6);
end
l = l+6;
end
 


währe schön wenn da jemand eine gute Idee hätte!

Gruß
 
MaFam
Forum-Meister

Forum-Meister


Beiträge: 799
Anmeldedatum: 02.05.12
Wohnort: ---
Version: R2009b
     Beitrag Verfasst am: 31.07.2012, 13:14     Titel:
  Antworten mit Zitat      
Hallo,

ich verstehe nicht ganz, warum du eine Interpolationsfunktion dafür bemühen willst.

Wenn ich dich richtig verstanden habe, dann betrachtest du die Matrix zeilenweise.

Angenommen eine Zeile sieht folgendermaßen aus:

5 6 8 NaN NaN NaN 20

Dann kannst du rechnen a_i=\frac{20-8}{n-0}*i+8 mit n=4 und ersetzen

5 6 8 12/4*1+8 12/4*2+8 12/4*3+8 20

Falls die Elemente nicht sortiert sind. Dann kannst du polyfit mit Grad 1 auf x=1:n und y=zeile(1):zeile(n) anwenden, wobei die NaN vorher entfernt werden.

Grüße, Marc
Private Nachricht senden Benutzer-Profile anzeigen
 
klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 31.07.2012, 14:14     Titel:
  Antworten mit Zitat      
Hey,

tut mir leid, aber irgendwie versteh ich deinen Lösungsvorschlag nicht bzw. weiss nicht, wie ich ihn auf meinen Code anwenden kann. Kannst du das nochmal genauer erläutern, oder an einem Beispiel zeigen?
z.B. für diese Matrix: A = (1 2 3 4 NaN NaN 2 5 6 NaN NaN NaN NaN NaN NaN NaN 7 8 Nan 9)

wobei ja hier die 2. NaN Folge >= 7 ist und somit nicht beachtet werden soll. Also so stehenbleiben soll.

Das währe super.

Gruß
 
MaFam
Forum-Meister

Forum-Meister


Beiträge: 799
Anmeldedatum: 02.05.12
Wohnort: ---
Version: R2009b
     Beitrag Verfasst am: 31.07.2012, 16:18     Titel:
  Antworten mit Zitat      
Ist das richtig, dass du die Matrix zeilenweise behandelst? Gut, nehmen wir an, man hätte die Zeile a = (1 2 3 4 NaN NaN 2 5 6 NaN NaN NaN NaN NaN NaN NaN 7 8 Nan 9) . Der zu identifizierende Bereich wäre dann a_part=(4 NaN NaN 2)? Das muss man erst mal klären. Wenn dem so ist, soll also absteigend von 4 nach 2 linear interpoliert werden? Wenn auch dem so ist, dann eignet sich meine obige Formel. Zur Identifizierung der relevanten Bereiche siehe hier: http://www.gomatlab.de/x-aufeinande.....vektor-suchen-t13243.html
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: 01.08.2012, 02:27     Titel:
  Antworten mit Zitat      
Hallo klaus1,

Dies interpoliert alle NaNs linear und einigermaßen schnell:
Code:
A = [1 2 3 4 NaN NaN 2 5 6 NaN NaN NaN NaN NaN NaN NaN 7 8 NaN 9];
valid = ~isnan(A);
good = find(valid);
A(~valid) = interp1(good, A(valid), find(~valid));

Nun muss man noch die zu langen Sequenzen ausschließen. MaFam's Link ist dabei hilfreich. Versuche es mal und frage bei Problemen weiter.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
MaFam
Forum-Meister

Forum-Meister


Beiträge: 799
Anmeldedatum: 02.05.12
Wohnort: ---
Version: R2009b
     Beitrag Verfasst am: 01.08.2012, 09:01     Titel:
  Antworten mit Zitat      
Ich würde hier zunächst klären, ob global oder lokal interpoliert werden soll. Das erscheint mir nämlich nicht selbstverständlich.
Private Nachricht senden Benutzer-Profile anzeigen
 
klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.08.2012, 11:41     Titel:
  Antworten mit Zitat      
Hallo,

was genau meinst du denn mit global und lokal?
Also die Matrix soll zeilenweise linear interpoliert werden, so wie es der Vorschlag von Jan auch macht.
Ich habe mir den Link einmal angeschaut und das, was Jan da als Lösung vorgeschlagen hat, also:

Code:

Laenge  = 4;
A       =  (rand(1, 1e8) > 0.5);  % Beispiel Daten
Start  = strfind(A, [0, ones(1, Laenge)]) + 1;
if all(A(1:Laenge)  == 1)
  Start = [1, Start];
end
Ende = strfind(A, [ones(1, Laenge), 0]) + (Laenge - 1);
if all(A(end - Laenge + 1:end)  == 1)
  Ende = [Ende, length(A)];
end
 


Allerdings weiss ich nicht genau wie ich das jetzt für NaN Werten übertragen soll

Danke schonmal für die Hilfe
Gruß
 
MaFam
Forum-Meister

Forum-Meister


Beiträge: 799
Anmeldedatum: 02.05.12
Wohnort: ---
Version: R2009b
     Beitrag Verfasst am: 01.08.2012, 13:41     Titel:
  Antworten mit Zitat      
Hm, gut dann wäre das die globale Variante, die ich meinte. Ist denn von einem linearen Verhalten der Daten auszugehen? Was steckt hinter der Problemstellung? Stehen in der Matrix irgendwelche Messreihen nach der Zeit? Im Zweifel würde ich eher lokal linearisieren. Damit meine ich, dass man sich eine NaN-Folge + Rand herausnimmt, dann die beiden Werte am Anfang und am Ende der Reihe linear interpoliert. Dazu benötigt man keine weiteren Kenntnisse über das "globale" Systemverhalten.
Private Nachricht senden Benutzer-Profile anzeigen
 
klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.08.2012, 13:57     Titel:
  Antworten mit Zitat      
Also bei der Matrix handelt es sich um eine Temperatur - bzw. Feuchtemessreihe von 26 Stationen. Die Daten liegen in 10-Minuten Werten vor, insofern kann man annehmen, dass die Temperatur/Feuchte von Wert zu Wert sich nur linear ändert. Da man somit keinen globalen Trend setzten kann, ist es sinvoller dann lokal zu linearisieren. Ich dachte genau das macht der Vorschlag von Jan auch, oder nicht? Deswegen auch die Begrenzung auf max. 6 Werte, da man ab dann wohl nichtmehr linear interpolieren kann. Es geht im Endeffekt nur um eine Reduzierung der NaN-Werte.

Ich hab mir jetzt Anhand des Links von dir etwas in der Art für mein Problem versucht zu programieren, leider funktioniert das nicht.

Code:

A   =  Matrix(1,:);
B = ~isnan(A);
Laenge  =6;


Start  = strfind(B, [0, ones(1, Laenge)]) + 1;
if all(B(1:Laenge)  == 1)
    Start = [1, Start];
end
Ende = strfind(B, [ones(1, Laenge), 0]) + (Laenge - 1);
if all(B(end - Laenge + 1:end)  == 1)  
  Ende = [Ende, length(B)];


for i = 1:1044 % Länge von dem Startvektor -1
if Start(i+1) - Ende(i) < 6
valid = ~isnan(A(1,Ende(i)-1:Start(i+1)+1));
good = find(valid);
A(~valid) = interp1(good, A(valid), find(~valid));
end
end

leider führt Matlab so keine Interpolation durch

Außerdem funktioniert der obige Code nur für einen Vektor. Besser währe natürlich gleich die ganze Matrix zu interpolieren, allerdings habe ich das nicht hinbekommen.


 
 
MaFam
Forum-Meister

Forum-Meister


Beiträge: 799
Anmeldedatum: 02.05.12
Wohnort: ---
Version: R2009b
     Beitrag Verfasst am: 01.08.2012, 14:52     Titel:
  Antworten mit Zitat      
Gut, dann greife besser zu der lokalen Variante! Dazu identifiziert du die relevanten Bereiche und linearisiert über deren Ränder mit der Formel, die ich oben schon angeben habe.
Mit einer Schleife überträgst du die zeilenweise Betrachtung auf die gesamte Matrix. Was den Code betrifft, kann ich erst heute Abend Hilfestellung leisten. Vielleicht bekommst du das aber auch alleine hin bis dahin...

Edit: Meine Formel lässt sich auch mit linspace realisieren.

Code:

% a - Anfangswert
% b - Endwert
% n- Schrittweite (hier die Anzahl der NaN+1)
y = linspace(a,b,n)
 
Private Nachricht senden Benutzer-Profile anzeigen
 
klaus1

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.08.2012, 15:06     Titel:
  Antworten mit Zitat      
okay, ich habs fast hinbekommen

hier der Code, falls es interessiert

Code:

for k = 1:25
A   =  a.tmat2(k,:);
B = ~isnan(A);
Laenge  =6;

B2 = zeros(1,84096);
for i = 1:84095
B2(i) = B(i)-B(i+1);
end
start = find(B2==1);
ende = find(B2==-1);

for i = 1:length(start)-1
   
if ende(i) - start(i) < 6
valid = ~isnan(A(1,start(i):ende(i)+1));
good = find(valid);
A2 = A(start(i):ende(i)+1);
A(~valid) = interp1(good, A2(valid), find(~valid));
A(start(i)+1:ende(i)) = A(~valid);

end
end
A3(k,:) = A;
end
A3(26,:) = a.tmat2(26,:);
% Die letzte Zeile musste ich extra machen, da dort keine  Fehlwerte drin sind
 


Ab k = 4 wird dann leider keine Interpolation mehr durchgeführt, ich weiss noch nicht warum. Muss wohl ein formaler Fehler irgendwo im Code sein.(den sollte ich ja eigendlich finden)

Also erstmal Danke für die Hilfe

Gruß
 
MaFam
Forum-Meister

Forum-Meister


Beiträge: 799
Anmeldedatum: 02.05.12
Wohnort: ---
Version: R2009b
     Beitrag Verfasst am: 01.08.2012, 15:16     Titel:
  Antworten mit Zitat      
Ich habe mir Jans Code jetzt mal kurz angeschaut, dieser macht tatsächlich eine lokale Interpolation. Ich hatte den Code dann wohl falsch verstanden. Vielleicht ist linspace dennoch schneller? Man könnte das mal versuchen...
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.