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,;
X = 1:length(Matrix(1,);
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: ---
Verfasst am: 31.07.2012, 13:12
Titel:
edit:
okay hier mal ein Code wie es bei mir funtioniert. Allerdings braucht mein Matlab dafür >12 Minuten
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 ifsum(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
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 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
klaus1
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 31.07.2012, 14:14
Titel:
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.
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
Ich würde hier zunächst klären, ob global oder lokal interpoliert werden soll. Das erscheint mir nämlich nicht selbstverständlich.
klaus1
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 01.08.2012, 11:41
Titel:
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;
ifall(A(1:Laenge) == 1)
Start = [1, Start];
end
Ende = strfind(A, [ones(1, Laenge), 0]) + (Laenge - 1);
ifall(A(end - Laenge + 1:end) == 1)
Ende = [Ende, length(A)];
end
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.
klaus1
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 01.08.2012, 13:57
Titel:
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.
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.
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)
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)
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...
Einstellungen und Berechtigungen
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.