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

Vektor mit Indizes benutzen um Felder auszulesen. Ohne For

 

einfachrolf
Forum-Anfänger

Forum-Anfänger


Beiträge: 11
Anmeldedatum: 03.10.14
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 03.10.2014, 14:58     Titel: Vektor mit Indizes benutzen um Felder auszulesen. Ohne For
  Antworten mit Zitat      
Ich würde gerne meine for-Schleife ersetzen.


Code:
% Das Programm:
a_1 = [1, 3,  5];
a_2 = [5,10,20]; % jedem Wert aus a_1 wird ein Wert zugordnet. (1->5, 3->10, 5->20)

b_1 = [3,3,3,5,1];
b_2 = zeros(1,size(b_1,1)); % Initialisierung des Lösungsvektors: b_2 = [0,0,0,0,0]; Wobei die Nullen ersetzt werden sollen.

% in b_1 stehen nun Werte aus a_1. In b_2 sollen nun die entsprechenden Werte aus a_2 stehen. Der Lösungsvektor ergäbe also: b_2 = [10, 10, 10, 20, 5].



% folgende for- Schleife würde das Problem lösen.
for i = 1 : size(b_1,2)
  [wert index] = find( a_1==b_1(i),1,'last' ); % die 1 und das last könnte man sich hier auch sparen.
  b_2(i) = a_2(index);
end
 



Die Lösung mit der For-Schleife kann ich mir leider nicht leisten.

Wie würdet ihr am elegantesten diese For-Schleife umgehen?

Ich habe irgendwie das Gefühl, dass die Lösung eigentlich sehr einfach ist, ich sie aber gerade nicht sehe.
Private Nachricht senden Benutzer-Profile anzeigen


DSP
Forum-Meister

Forum-Meister



Beiträge: 2.117
Anmeldedatum: 28.02.11
Wohnort: ---
Version: R2014b
     Beitrag Verfasst am: 03.10.2014, 17:03     Titel:
  Antworten mit Zitat      
Warum sollte eine Ausdruck ohne Schleife wirklich viel schneller sein? In meinen Augen wird viel zu oft nach Ausdrücken ohne Schleife gefragt, die aber eher selten einen Performance Vorteil bringen, erst recht wenn die Matrizen recht kurz sind.

In deinem Fall wirst du aber auf die Schleife nicht verzichten können, wenn a_1 und b_1 eine unterschiedliche Anzahl an Elementen haben. Man könnte aber allein schon die Laufzeit verkürzen, wenn die Anzahl an Umläufen nach dem kürzeren Array a_1 ausgelegt ist.

Code:

for i = 1 : size(a_1,2)
  [~,index] = find(b_1==a_1(i));
  if ~isempty(index)
    b_2(index) = a_2(i);
  end
end
 
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: 03.10.2014, 19:03     Titel: Re: Vektor mit Indizes benutzen um Felder auszulesen. Ohne F
  Antworten mit Zitat      
Hallo einfachrolf,

Der 2. Output von ISMEMBER wäre hier hilfreich. Bei größeren Datenmengen ist das effizienter, weil es die Inputs sortiert und die viel schnellere Binary Search angewendet wird.

Wenn es um die Performance geht, ist eine korrekte pre-allocation wichtig.
b_2 wird mit "size(b_1,1)" Elementen vordefiniert, später werden aber bis zu "size(b_1,2)" Elemente hineingeschrieben in Deinem Code.

Diese Zeile sieht merkwürdig aus:
Code:
[wert index] = find( a_1==b_1(i),1,'last' );

FIND gibt den row und column Index aus, wenn es zwei Outputs zurück gibt. Dazu passen die Variablennamen "wert" und "index" nicht. Das klingt eher nach MAX oder MIN.

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

Forum-Anfänger

Forum-Anfänger


Beiträge: 11
Anmeldedatum: 03.10.14
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 03.10.2014, 20:30     Titel:
  Antworten mit Zitat      
DSP hat Folgendes geschrieben:
Warum sollte eine Ausdruck ohne Schleife wirklich viel schneller sein? In meinen Augen wird viel zu oft nach Ausdrücken ohne Schleife gefragt, die aber eher selten einen Performance Vorteil bringen, erst recht wenn die Matrizen recht kurz sind.


Natürlich sind die Matrizen in den Beispielen sehr klein.

Ich möchte statt den Schleifen versuchen möglichst auf Matlab-builtin Funktionen zurückgreifen.

Dies konnte ich durch einen komplizierten Umweg auch bereits erreichen und einiges an Rechenzeit einsparen. (Bei einigen Operationen fiel so die Rechenzeit von 30sec auf ca 1sec. Da ich einige dieser Operationen durchführe macht dies in der Summe einiges aus)
Private Nachricht senden Benutzer-Profile anzeigen
 
einfachrolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 11
Anmeldedatum: 03.10.14
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 03.10.2014, 20:35     Titel: Re: Vektor mit Indizes benutzen um Felder auszulesen. Ohne F
  Antworten mit Zitat      
Jan S hat Folgendes geschrieben:

Der 2. Output von ISMEMBER wäre hier hilfreich. Bei größeren Datenmengen ist das effizienter, weil es die Inputs sortiert und die viel schnellere Binary Search angewendet wird.


Vielen Dank! Werde ich gleich mal ausprobieren


Jan S hat Folgendes geschrieben:

Wenn es um die Performance geht, ist eine korrekte pre-allocation wichtig.
b_2 wird mit "size(b_1,1)" Elementen vordefiniert, später werden aber bis zu "size(b_1,2)" Elemente hineingeschrieben in Deinem Code.


Soll natürlich in beiden Fällen size(b_1,2) heißen Wink.

Jan S hat Folgendes geschrieben:

Diese Zeile sieht merkwürdig aus:
Code:
[wert index] = find( a_1==b_1(i),1,'last' );

FIND gibt den row und column Index aus, wenn es zwei Outputs zurück gibt. Dazu passen die Variablennamen "wert" und "index" nicht. Das klingt eher nach MAX oder MIN.


Stimmt natürlich auch. Meine Konzentration hat schon etwas nachgelassen.
Private Nachricht senden Benutzer-Profile anzeigen
 
einfachrolf
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 11
Anmeldedatum: 03.10.14
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 03.10.2014, 20:59     Titel:
  Antworten mit Zitat      
Bisher in korrigierter Version:

Code:
a_1 = [1, 3,  5];
a_2 = [5,10,20]; % jedem Wert aus a_1 wird ein Wert zugordnet. (1->5, 3->10, 5->20)

b_1 = [3,3,3,5,1];
b_2 = zeros(1,size(b_1,2)); % Initialisierung des Lösungsvektors: b_2 = [0,0,0,0,0]; Wobei die Nullen ersetzt werden sollen.

% in b_1 stehen nun Werte aus a_1. In b_2 sollen nun die entsprechenden Werte aus a_2 stehen. Der Lösungsvektor ergäbe also: b_2 = [10, 10, 10, 20, 5].



% folgende for- Schleife würde das Problem lösen.
for i = 1 : size(b_1,2)
  [row, col] = find( a_1==b_1(i),1,'last' );
  b_2(i) = a_2(col);
end

% durch ismember bekomme ich
[loca, locb] = ismember(b_1,a_1);
 



locb liefert mir nun die Indizies, wo meine gewünschten Werte in a_2 stehen. Wie bekomme ich nun aus dem Vektor mit den Indizes den Vektor mit den Werten?


Dazu reicht es nun das Problem nochmal seperat zu betrachten in folgendem unabhängigen Code:
Code:

locb = [2 2 2 3 1];
a_2 = [5,10,20];

b_2 = ?

% Nun soll b_2 = [10, 10, 10, 20, 5] werden indem für die Indizes in locb jeweils die Werte aus a_2 eingetragen werden.
 
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: 05.10.2014, 22:05     Titel:
  Antworten mit Zitat      
Hab mir nur noch diesen Teil durchgelesen:
einfachrolf hat Folgendes geschrieben:
Dazu reicht es nun das Problem nochmal seperat zu betrachten in folgendem unabhängigen Code:
Code:

locb = [2 2 2 3 1];
a_2 = [5,10,20];

b_2 = ?

% Nun soll b_2 = [10, 10, 10, 20, 5] werden indem für die Indizes in locb jeweils die Werte aus a_2 eingetragen werden.
 


Hilft dir das?
Code:
b_2     = (locb==1)*a_2(1) + (locb==2)*a_2(2) + (locb==3)*a_2(3);


Code:
b_2 = zeros(1,size(locb,2));
for ii = 1:size(a_2, 2)
    b_2 = b_2 + (locb==ii)*a_2(ii);
end


Grüße
_________________

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

Forum-Anfänger

Forum-Anfänger


Beiträge: 11
Anmeldedatum: 03.10.14
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 07.10.2014, 02:49     Titel:
  Antworten mit Zitat      
Seban hat Folgendes geschrieben:


Hilft dir das?
Code:
b_2     = (locb==1)*a_2(1) + (locb==2)*a_2(2) + (locb==3)*a_2(3);


Code:
b_2 = zeros(1,size(locb,2));
for ii = 1:size(a_2, 2)
    b_2 = b_2 + (locb==ii)*a_2(ii);
end


Grüße


Dein erster Vorschlag ist leider nicht allgemein. Aber ein guter Ansatz wie ich finde. Da muss ich nochmal in Ruhe drüber nachdenken, ob man es irgendwie so verallgemeinern kann.

Genau das tust du zwar im nächsten Vorschlag, jedoch möchte ich keine Schleife benutzen. Deshalb bin ich noch nicht wirklich weiter.
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.