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

Werte mehrerer Spalten finden, vergleichen und eliminieren

 

kraudi13
Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 16.08.2015, 22:45     Titel: Werte mehrerer Spalten finden, vergleichen und eliminieren
  Antworten mit Zitat      
Hallo liebe MATLAB-Freunde,

ich habe folgendes Problem.
Im Anhang befindet sich die Beispieldatei, mit deren Daten ich folgenden Ablauf durchführen möchte.

Spalte 1 (t) ist die Zeit in Sekunden. Das System hat in unregelmäßigen Abständen Zeiten mehrfach aufgezeichnet.

Grundsätzlich sollen die Werte der Spalte 2 (Rf) < 90 sein. Die kompletten Zeilen, bei denen der Zellenwert > 90 beträgt, sollen eliminiert werden. Wenn folgende Bedingungen erfüllt werden:
-> Ist ein Zeitwert (t) mehrfach vorhanden?
JA: Überprüfe, ob in einem Bereich von t +- 3 Sekunden ein Rf < 90 zu finden ist.
wenn JA: lösche die komplette Zeile
wenn NEIN: beide Spalten (t und Rf) in neuer Variable speichern

Wie beschrieben möchte ich grundsätzlich pro Zeitwert einen Rf-Wert < 90 haben. Wenn einen Zeitwert aufgrund der beschriebenen Eliminierungen kein Rf-Wert mehr zugeordnet werden kann, dann kann die Toleranzgrenze der Zeit 9 Sekunden betragen.

sample.txt
 Beschreibung:

Download
 Dateiname:  sample.txt
 Dateigröße:  12.29 KB
 Heruntergeladen:  401 mal
Private Nachricht senden Benutzer-Profile anzeigen


Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 19.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 17.08.2015, 23:48     Titel:
  Antworten mit Zitat      
Hallo,

Einlesen der Daten: https://de.mathworks.com/help/matla.....to-import-text-files.html

Sollen Zeilen für Rf größer 90 nur eliminiert werden, wenn sich in dem Gebiet darum (idx-3:idx+3) keine Werte kleiner 90 befinden? Bedeutet eliminieren komplett entfernen oder auf NaN setzen?

Ein Ansatz:
Code:

t   = [1 2 3 3 4 5 5 5 5 6 11:20]';
Rf  = rand(20, 1) .* 100;

log_t   = [false(1); diff(t) == 0]; % 1 für Wiederholungen, sont 0
% log_Rf  = Rf > 90;                  % 1 für Werte größer 90
idx_t   = find(log_t);

for ii = 1:size(idx_t, 1)
    range = idx_t(ii) - 3:idx_t(ii) + 3;
    if any(Rf(range) <= 90)
        log_t(idx_t(ii)) = false;  
    end
end
n = [t(log_t), Rf(log_t)];
 


Grüße,
Seban
_________________

Richtig fragen
Debugging
Private Nachricht senden Benutzer-Profile anzeigen
 
kraudi13
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 18.08.2015, 07:29     Titel:
  Antworten mit Zitat      
Hallo Seban,

vielen Dank für die Antwort! Das ist schon mal super und geht in die Richtung, wie ich es mir vorstelle Smile

Zitat:
Sollen Zeilen für Rf größer 90 nur eliminiert werden, wenn sich in dem Gebiet darum (idx-3:idx+3) keine Werte kleiner 90 befinden?


Genau anders herum. Es sollen Zeilen für Rf größer 90 nur eliminiert werden, wenn sich in dem Gebiet darum mindestens ein Wert kleiner 90 befindet.

Zitat:
Bedeutet eliminieren komplett entfernen oder auf NaN setzen?


Die Zeilen sollen komplett entfernt werden.

Einfaches kleines Beispiel:

M=[
Zeile t Rf
1 1 43
2 2 74
3 3 46
4 3 86
5 4 46
6 5 49
7 5 94
8 5 22
9 5 8
10 6 6
11 11 88

12 12 23
13 13 86
14 14 71
15 15 87
16 16 93
17 17 13
18 18 39
19 19 98
20 20 64
]

In Zeile 7 taucht bei t=5 der Rf-Wert 94 auf. Dieser soll gelöscht werden. Die anderen Zeilen mit t=5 sollen erstmal bleiben (Und - zusätzlich - nach dem Filtern dann gemittelt zusammengefasst werden. Aber diesen Schritt am besten erstmal nicht berücksichtigen, sonst seh ich selbst nicht mehr durch Wink ).

Zeile 16 hat bei Rf = 93 zwar kein doppeltes Sample (nur t = 16 ), aber im festgelegten Bereich (idx-3:idx+3) befinden sich Rf-Werte kleiner 90. Diese Zeile soll somit ebenfalls gelöscht werden. Das gleiche gilt für Zeile 19 ( t = 19 mit Rf = 98 )

Zeile 10 und 11 erfüllen die Bedingung, dass die t-Werte nicht mehr als 9 Samples Abstand aufweisen.

Am Ende soll die Matrix dann wie folgt aussehen:

M_neu=[

Zeile t Rf
1 1 43
2 2 74
3 3 46
4 3 86
5 4 46
6 5 49
7 5 22
8 5 8
9 6 6
10 11 88
11 12 23
12 13 86
13 14 71
14 15 87
15 17 13
16 18 39
17 20 64
]


Hintergrund ist, dass das Messsystem zwar erkannt hat, dass Werte über 90 unrealistisch sind und dann versuchte, gleiche Samples mit realistischen Werten zu belegen. Das klappte in vielen Fällen und deswegen würde ich gern erstmal die unrealistischen Peaks wegbekommen.


Beste Grüße
kraudi
Private Nachricht senden Benutzer-Profile anzeigen
 
Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 19.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 18.08.2015, 15:12     Titel:
  Antworten mit Zitat      
Hallo Kraudi,

Code:

t   = [1 2 3 3 4 5 5 5 5 6 11:20]';
Rf  = [43   74   46   86   46   49   94   22   8   6   88   23   86   71   87   93   13   39   98   64]';

%% Rf größer 90
offset = 3;

Rf  = [NaN(offset,1); Rf; NaN(offset,1)];   % NaN nötig, falls range außerhalb des Vektors
t   = [NaN(offset,1); t; NaN(offset,1)];   % auch hier, um Länge der Vektoren gleich zu halten

log_Rf  = Rf > 90;      % 1 für Werte größer 90
idx_Rf  = find(log_Rf); % Indizes

del_row = false(size(log_Rf));
sz  = size(idx_Rf, 1);
n   = NaN(sz, 2);   % pre-allocate
for ii = 1:sz
    range = idx_Rf(ii) - offset:idx_Rf(ii) + offset;
    if any(Rf(range) <= 90)
        del_row(idx_Rf(ii)) = true; % zu löschende Zeilen ermitteln
    else
        n(ii, :) = [t(idx_Rf(ii)), Rf(idx_Rf(ii))];
    end
end

t(del_row)  = [];   % löschen
Rf(del_row) = [];

t   = t(offset+1:end-offset);     % NaN wieder entfernen
Rf  = Rf(offset+1:end-offset);

M_neu = [t, Rf];


%% Wiederholungen in t
log_t       = [false(1); diff(t) == 0]; % 1 für Wiederholungen, sont 0
start_idx_t = find(diff(log_t) == 1);
end_idx_t   = find(diff(log_t) == -1);

for ii = 1:size(start_idx_t, 1)
    range = start_idx_t(ii):end_idx_t(ii);
    Rf(start_idx_t(ii)) = sum(Rf(range)) ./ length(range);  % "Wiederholte" ersetzen
end

t(log_t)  = [];     % Wiederholungen löschen
Rf(log_t) = [];

M_neu = [t, Rf];


M_neu kann man auch am Anfang erzeugen und dann damit weiterarbeiten anstatt mit t und Rf.
del_row braucht es nicht unbedingt, stattdessen log_Rf weiter verwenden und in else auf false setzen, statt in if auf true.

Die 9-Sample-Bedingung ist mir noch nicht ganz klar. Was soll zB geschehen, wenn zw. zwei t ein Abstand >9 vorliegt?

Grüße,
Seban
_________________

Richtig fragen
Debugging
Private Nachricht senden Benutzer-Profile anzeigen
 
kraudi13
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 18.08.2015, 16:26     Titel:
  Antworten mit Zitat      
Hallo Seban,

super ding!
Wie würde das dann aussehen, wenn M_neu schon anfangs erzeugt wird?

Ich stehe jetzt nämlich vor dem Problem, dass ich bis zum löschen der Zeilen mit Rf > 90 komme. Dann würde ich auf Grundlage von del_row gleich in der in der Hauptmatrix (16 Spalten) alles anwenden. Wenn ich das bei der Matrix (N) anwende, macht er aus einer 649x16 double eine 1x10374 double.

Code:
N(del_row)  = [];
 


Und wie schaut das dann im folgenden Verlauf mit den Wiederholungen aus? Wie schaut die Funktion für

Code:

    Rf(start_idx_t(ii)) = sum(Rf(range)) ./ length(range);
 


bei dann N aus?

Zitat:
Die 9-Sample-Bedingung ist mir noch nicht ganz klar. Was soll zB geschehen, wenn zw. zwei t ein Abstand >9 vorliegt?


-> würde ich nach Lösung des oben stehenden Problems nochmal aufgreifen Smile

Vielen Dank schon Mal für die super Hilfe!

Beste Grüße
kraudi
Private Nachricht senden Benutzer-Profile anzeigen
 
Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 19.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 18.08.2015, 22:02     Titel:
  Antworten mit Zitat      
Hi,

Bei Matrizen musst du Zeilen- und Spaltenindizes angeben.

kraudi13 hat Folgendes geschrieben:
Ich stehe jetzt nämlich vor dem Problem, dass ich bis zum löschen der Zeilen mit Rf > 90 komme. Dann würde ich auf Grundlage von del_row gleich in der in der Hauptmatrix (16 Spalten) alles anwenden. Wenn ich das bei der Matrix (N) anwende, macht er aus einer 649x16 double eine 1x10374 double.

Code:
N(del_row, :)  = [];


kraudi13 hat Folgendes geschrieben:
Und wie schaut das dann im folgenden Verlauf mit den Wiederholungen aus? Wie schaut die Funktion für
Code:
Rf(start_idx_t(ii)) = sum(Rf(range)) ./ length(range);

bei dann N aus?

Code:
N(start_idx_t(ii), 2) = sum(N(range, 2)) ./ length(range); % angenommen 2. Spalte = Rf


https://de.mathworks.com/help/matla.....atlab/array-indexing.html

Grüße,
Seban
_________________

Richtig fragen
Debugging
Private Nachricht senden Benutzer-Profile anzeigen
 
kraudi13
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 19.08.2015, 14:20     Titel:
  Antworten mit Zitat      
Hallo nochmal,

also das ist erste Sahne Smile Vielen Dank dafür. Das läuft so, wie ich es mir gedacht hab.
Bzgl. der 9-Sekunden-Regel. Das lässt sich in diesem Kontext nicht wirklich realisieren.

Wichtiger wäre mir noch ein weiteres Problem:
Ich würde gern einen bestimmten Bereich in der Matrix auswählen und als neue Matrix speichern.

In Spalte 1 stehen ja die Zeitsamples.
Der Bereich soll von vorn herein schon klar definiert sein. Zum Beispiel von 5 bis 15.

Code:
M =[
    1   27
    2   16
    3   32
    4   19
    5   23 % Startzeile
    6   11
    8   25
    9   73
   10   80
   13   85
   14   69
   15   13 % Endzeile
   16   45
   17   73
   18   24
   19   69
];


Nun möchte ich gern aus diesem Bereich ähnlich der folgenden Funktion das Maximum etc. berechnen.

Code:
startwert = M(5:,1); % aber für den Wert 5 bzw. den nächsthöheren vorhanden Wert, falls 5 nicht existiert
endwert = M(end-4,1); % für den Wert 15 (Ende abzüglich 4 Sekunden) bzw. den nächsthöheren vorhanden Wert, falls 15 nicht existiert.
[y_max, x_max] = max(M(startwert:endwert,2));


Allerdings sieht mein Beispiel ja vor, das ganze mit den Zeilen zu durchlaufen und nicht mit den Werten in Spalte 1.

Beste Grüße
kraudi
Private Nachricht senden Benutzer-Profile anzeigen
 
Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 19.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 19.08.2015, 22:39     Titel:
  Antworten mit Zitat      
Gern geschehen.

Wenn 5 und 15 in M(:,1) enthalten:
Code:
startwert   = find(M(:,1) == 5, 1, 'first');
endwert     = find(M(:,1) == 15, 1, 'last');
[MX, I]     = max(M(startwert:endwert,2));   % gibt Maximalwert und dessen Index zurück, nicht x und y, wie dein Code-Bsp. vermuten lässt

Dies lässt sich wie oben wieder mit (logischen) Vergleichsoperatoren und find lösen.

Wenn die Werte nicht zwingend vorhanden sind, könnte man quick & dirty die Suche nach Start-/Endwert in Schleifen gestalten. Die Schleife für den startwert bspw. von min_grenze bis max_grenze und für den endwert von max_grenze bis zum Maximal-/Endwert des Vektors.

Grüße,
Seban
_________________

Richtig fragen
Debugging
Private Nachricht senden Benutzer-Profile anzeigen
 
kraudi13
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 20.08.2015, 01:58     Titel:
  Antworten mit Zitat      
So passt das! 1A! Danke!

Zitat:
Wenn die Werte nicht zwingend vorhanden sind, könnte man quick & dirty die Suche nach Start-/Endwert in Schleifen gestalten. Die Schleife für den startwert bspw. von min_grenze bis max_grenze und für den endwert von max_grenze bis zum Maximal-/Endwert des Vektors.


Ich hab das jetzt der einfach halt halber wie folgt gelöst und das funktioniert ganz ordentlich.

Code:
[I min_wert]=min(abs(M(:,1)-5));
[I max_wert]=min(abs(M(:,1)-15));
start_wert = M(min_wert,1);
end_wert = M(max_wert,1);


Beste Grüße
Tino
Private Nachricht senden Benutzer-Profile anzeigen
 
kraudi13
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 20.08.2015, 12:34     Titel:
  Antworten mit Zitat      
Hello again,

jetzt sind doch noch zwei unschöne Fehlermeldung aufgetaucht. Das Ganze passiert aber in jeweils unterschiedlichen Dateien.

1. Meldung (Matrixdimension: 848x16)

Code:

??? Attempted to access M(1,370); index out of bounds because size(M)=[848,16].

Error in ==> at 14
        n(ii, :) = [M(1,idx_Rf(ii)), M(2,idx_Rf(ii))];
 


2. Meldung (Matrixdimension: 446x16)

Code:
??? Attempted to access end_idx_t(13); index out of bounds because
numel(end_idx_t)=12.

Error in ==> at 30
     range = start_idx_t(ii):end_idx_t(ii);


Andere Dateien funktionieren aber einwandfrei.
Private Nachricht senden Benutzer-Profile anzeigen
 
Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 19.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 20.08.2015, 15:02     Titel:
  Antworten mit Zitat      
Hallo,

Code:
??? Attempted to access M(1,370); index out of bounds because size(M)=[848,16].

Error in ==> at 14
        n(ii, :) = [M(1,idx_Rf(ii)), M(2,idx_Rf(ii))];

Wie die Meldung schon sagt, versuchst du auf Spalte 370 von M zuzugreifen, M hat aber nur 16 Spalten (und 848 Zeilen). Freundlicherweise nennt Matlab auch noch wo dieser Zugriff geschehen soll (Zeile 14).

Code:
??? Attempted to access end_idx_t(13); index out of bounds because
numel(end_idx_t)=12.

Error in ==> at 30
     range = start_idx_t(ii):end_idx_t(ii);

Dasselbe in Grün, du versuchst auf Element 13 von end_idx_t zuzugreifen, obwohl es nur 12 Elemente enthält.

Warum dies geschieht bleibt ohne Beispielcode und -daten nur zu erraten.

Grüße,
Seban
_________________

Richtig fragen
Debugging
Private Nachricht senden Benutzer-Profile anzeigen
 
kraudi13
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 20.08.2015, 23:21     Titel:
  Antworten mit Zitat      
Ok,

dann folgen zwei Beispiele und die jeweils dazugehörigen Beispieldateien.

Code:
M = csvread('data2');
offset = 3;
%
M  = [NaN(offset,16); M; NaN(offset,16)];
log_column  = M(:,2) > 90;    
idx_Rf  = find(log_column); % Indizes
del_row = false(size(log_column));
sz  = size(idx_Rf, 1);
n   = NaN(sz, 2);   % pre-allocate
for ii = 1:sz
    range = idx_Rf(ii) - offset:idx_Rf(ii) + offset;
    if any(M(range,2) <= 90)
        del_row(idx_Rf(ii)) = true; % zu löschende Zeilen ermitteln
    else
        n(ii, :) = [M(1,idx_Rf(ii)), M(2,idx_Rf(ii))];
    end
end
% Zeilen löschen, die über dem Referenzbereich liegen.
M(del_row, :)  = [];
% NaN entfernen
M   = M(offset+1:end-offset,1:16);  
%
t = M(:,1);
log_t       = [false(1); diff(t) == 0]; % 1 für Wiederholungen, sont 0
start_idx_t = find(diff(log_t) == 1);
end_idx_t   = find(diff(log_t) == -1);
for ii = 1:size(start_idx_t, 1)
     range = start_idx_t(ii):end_idx_t(ii);
     M(start_idx_t(ii), 2:16) = sum(M(range, 2:16)) ./ length(range);  % "Wiederholte" ersetzen
 end
M(log_t, :) = [];


Mit diesem Datensatz kommt bei mir die erste Fehlermeldung. Mit dem zweiten folglich die zweite.

data2.txt
 Beschreibung:
für Fehlermeldung 2

Download
 Dateiname:  data2.txt
 Dateigröße:  19.88 KB
 Heruntergeladen:  360 mal
data1.txt
 Beschreibung:
für Fehlermeldung 1

Download
 Dateiname:  data1.txt
 Dateigröße:  20.72 KB
 Heruntergeladen:  317 mal
Private Nachricht senden Benutzer-Profile anzeigen
 
kraudi13
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 18.04.13
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 23.09.2015, 19:20     Titel:
  Antworten mit Zitat      
Hallo liebe Matlab-Gemeinde,

ist es schon irgendjemandem gelungen, in dem Problem einen Fortschritt zu verzeichnen?
Ich bin immer noch ratlos.

Beste Grüße
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.