Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   
Bücher:

Studierende:
weitere Angebote

Partner:


Vermarktungspartner


Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Datensatz mit 69k Zeilen einlesen --> langsam?

 

include

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.02.2008, 13:07     Titel: Datensatz mit 69k Zeilen einlesen --> langsam?
  Antworten mit Zitat      
Hallo community

Ich habe hier ein kleines problem: Mir liegt ein Datensatz als Text-datei vor, welche etwa wie folgt aussieht:

2132;1974.01.01 00:00; 5.565
2132;1974.01.01 19:46; 5.403
und weitere 69k zeilen.


Zur zeit benutze ich zum einlesen folgenden matlab-script:
Code:
...

while feof(fid)==0
    s=fgetl(fid);
    time=[time;s(6:21)];
    runoff=[runoff;s(23:30)];
end

runoff  = str2num(runoff)
time    = datenum(time,'yyyy.mm.dd HH:MM')
...


Als ergebnis erhalte ich zwei Spaltenvektoren (runoff und time).
ich hab testhalber mal ne ausgabe reingepackt, wie weit der fortschritt ist. (zb alle 1000 datensätze ein "dong!")

dabei stellte ich fest, dass so ab 7000 einträge bereits ein massives abbremsen des programmes festzustellen ist.

ich gehe davon aus, dass vor allem die zeilen
time=[time;s(6:21)];
runoff=[runoff;s(23:30)];
dafür verantwortlich gemacht werden müssen.



kennt ihr vielleicht eine optimalere methode dafür?

zB eine möglichkeit, ein STRING an das Ende eines spaltvektors zu hängen, ohne dass dabei ständig der vollständige vektor geladen werden muss. ein weiteres problem liegt zudem darin, dass matlab den string s(x:y) oft auch als vektor von CHARs betrachtet, und es daher auch zu fehlern bei matrixoperationen kommen kann. (nicht in dem beispiel oben, dieser script funktioniert. ich hab nur beim rumbasteln festgestellt, dass einige operationen deswegen nicht funktionieren)


tompie
Forum-Guru

Forum-Guru


Beiträge: 260
Anmeldedatum: 19.09.07
Wohnort: München
Version: immer alles
     Beitrag Verfasst am: 27.02.2008, 13:53     Titel:
  Antworten mit Zitat      
Hallo,

das Problem liegt darin, daß sich die String-arrays "time" und "runoff" während der Programmlaufzeit immer weiter vergrößern. Das ist bei kleinen Arrays kein Problem, aber bei größeren - so wie bei Dir - eben schon. Wenn Du vorher weißt, wieviele Zeilen Du einliest, solltest Du die Arrays vorher mit Leerstrings belegen und dann einen Zeilenzähler "z" hochlaufen lassen. Die Zuordnungen müsstest Du dann wie folgt machen:

Code:
time(z,:) = s(6:21);
runoff(z,:) = s(23:30);


Alternativ kannst Du auch Zellen verwenden:

Code:
time{z} = s(6:21);
runoff{z} = s(23:30);


Hoffe das hilft!

Gruß tompie
Private Nachricht senden Benutzer-Profile anzeigen
 
tompie
Forum-Guru

Forum-Guru


Beiträge: 260
Anmeldedatum: 19.09.07
Wohnort: München
Version: immer alles
     Beitrag Verfasst am: 27.02.2008, 13:54     Titel:
  Antworten mit Zitat      
Hallo,

das Problem liegt darin, daß sich die String-arrays "time" und "runoff" während der Programmlaufzeit immer weiter vergrößern. Das ist bei kleinen Arrays kein Problem, aber bei größeren - so wie bei Dir - eben schon. Wenn Du vorher weißt, wieviele Zeilen Du einliest, solltest Du die Arrays vorher mit Leerstrings belegen und dann einen Zeilenzähler "z" hochlaufen lassen. Die Zuordnungen müsstest Du dann wie folgt machen:

Code:
time(z,:) = s(6:21);
runoff(z,:) = s(23:30);


Alternativ kannst Du auch Zellen verwenden:

Code:
time{z} = s(6:21);
runoff{z} = s(23:30);


Hoffe das hilft!

Gruß tompie
Private Nachricht senden Benutzer-Profile anzeigen
 
include

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.02.2008, 14:03     Titel:
  Antworten mit Zitat      
hmmm, bedingt.

das problem ist, dass ich mehrere solcher files habe, und die nacheinander durchrechnen muss. (daher auch die frage nach optimierung... eine stunde pro file warten ist zu mühsam)

die files sind leider unterschiedlich lange.



zur zeit experimentiere ich mit folgender syntax:

time(end+1)= datenum(s(6:21),'yyyy.mm.dd HH:MM');

dies erzeugt allerdings ein zeilenvektor, welches sich abschliessend in einen spaltenvektor transformieren lässt. daran scheitert es nicht.

das ding bringt schon eine spürbare verbesserung der situation.
ABER:

ich würde gerne noch den aufruf der funktion datenum aus der schleife entfernen, und am schluss mit der transformation durchführen. (also den gesamten vektor auf einmal umwandeln lassen, statt jedes element separat)

schreibe ich nun aber
time(end+1)= s(6:21);

verweigert matlab den dienst:
In an assignment A(I) = B, the number of elements in B and
I must be the same.


ich glaube, das liegt daran, dass s(6:21) ein "array of char" erzeugt, welches dann nicht als einheit dem vektor "time" angefügt wird, sondern für jedes element ein eigenes, neues datenfeld.


gibt es eine schnelle funktion, welche ich aufrufen kann, um s(6:21) als einfaches string dem vektor time zu übergeben?
 
include

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.02.2008, 14:22     Titel:
  Antworten mit Zitat      
oder könnte man evtl sogar die Funktion datenum optimieren?
ich weiss ja nicht, wie's bei der funktion so mit der laufzeit ausschaut.

bei mir ist ja das datums-format bekannt und bei allen files exakt gleich. dass dann für jede zeile 'yyyy.mm.dd HH:MM' von neuem geparst werden muss, scheint irgendwie etwas sinnlos. oder nicht?
 
Bijick
Ehrenmitglied

Ehrenmitglied



Beiträge: 914
Anmeldedatum: 18.06.07
Wohnort: Nürnberg
Version: R2006b, R2008b
     Beitrag Verfasst am: 27.02.2008, 16:46     Titel:
  Antworten mit Zitat      
Hallo include,

ich würde textscan anstelle von fgetl verwenden:

Code:
fid = fopen('test.dat');
S = textscan(fid,'%f%16s%f','delimiter',';');
runoff = S{3};
time = datenum(S{2},'yyyy.mm.dd HH:MM');
fclose(fid);


Da braucht man gar keine Schleife und zumindest bei 26 Zeilen ist es schneller. Wenn Du einen Header hast, kann textscan den auch berücksichtigen.

Herzliche Grüße
Bijick
_________________

>> why
Private Nachricht senden Benutzer-Profile anzeigen E-Mail senden
 
include

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 27.02.2008, 17:30     Titel: resultat
  Antworten mit Zitat      
sry, hab deine post zu spät gelesen. bin jetzt mehr oder weniger fertig mit optimieren.

vorher benötigte der prozess ungefähr 54sec für 50'000 zeilen. nach umfangreicher optimierung konnte diese zeit auf 6 sec gedrückt werden.

wie das?
erstens konnte die funktionsaufrufe von datenum aus der schleife entfernt werden. durch die verwendung von str2double statt str2num und weiteren kleinigkeiten konnte die zeit von 54sec auf 37sec gedrückt werden.

anschliessend befolgte ich den vorher genannten tipp, dass man einen initialisierten vektor verwenden soll. das war der knüller schlechthin.
hab zwei riesige zero-vektoren definiert, was die rechenzeit auf die besagten 6sec drückte!
klasse!!!

(hab nämlich noch ein file mit über 400k zeilen gefunden, welches noch bearbeitet werden muss. und lieber warte ich 2min statt 30min... *G*)



danke an alle, die mir hier tipps und tricks gegeben haben. (auch in anderen threads, auf die ich dank suchmaschine gestossen bin)

und hier meine lösung: (schade, dass TAB nicht in der formatierung übernommen wird)

Code:

% m-file for reading in/ import BAfU data into matlab

clear all;                      % Säubere den Speicher von unnötigen Daten
clc;                            % Säubere die Arbeitsumgebung von Matlab

MAX_LINES = 600000;            
time=zeros(MAX_LINES,1);        % Initialisiere Vektoren (maximaler Umfang)
runoff=zeros(MAX_LINES,1);


%--------------------------------
fid=fopen('Abfluss_549.asc');
%Aussehen der Datei, welche eingelesen wird:
%   00549 / 2132 Töss-Neftenbach 01.01.1974-01.06.2007
%   Abfluss m³/s
%
%    2132;1974.01.01 00:00;   5.565
%    2132;1974.01.01 00:01;   5.565
% ...

s=fgetl(fid);                   % Erste Input-Zeile enthält ID des Einzugsgebietes
disp(['Bearbeitung der Daten vom Einzugsgebiet ' s(1:5)]);

fgetl(fid);                     % Zeile mit nutzlosem Inhalt
fgetl(fid);                     % Leere Zeile

disp('Warnung, der folgende Prozess benötigt extrem viel Zeit!  (Abbruch durch CTRL+C)');
disp('-------------------------------------------');
tic

i=0;                            % Lauf-Parameter
while feof(fid)==0 && i<MAX_LINES
    i=i+1;

    s=fgetl(fid);               % Zeile einlesen
                                % Format: 'blah;yyyy.mm.dd HH:MM'
    time(i)= str2double([s(6:9) s(11:12) s(14:15) s(17:18) s(20:21)]);
    runoff(i)=str2double( s(23:30));    % str2double soll schneller sein als str2num

    if mod(i,10000)==0          % alle 10k zeilen eine Notiz ausgeben
       disp(['Zeile Nummer ' int2str(i) ' eingelesen...']);
    end
end

disp('-------------------------------------------');
disp(['Arbeit abgeschlossen. Benötigte Zeit: ' num2str(toc) ' sec']);

if (i >= MAX_LINES)             % es könnte ja sein, dass das inputfile grösser als erwartet ist...
    disp(' ACHTUNG: es besteht der Verdacht, dass nicht ganz alle Zeilen bearbeitet werden konnten!');
end


time = time(1:i);               % Schneide die überschüssigen Einträge aus dem Array weg
runoff = runoff(1:i);          

    yyyy=floor(time./1e8);      % Extrahiere aus dem double nun die Jahreszahl
    time=time-yyyy.*1e8;        % und alle anderen daten...
    mm=floor(time./1e6);        
    time=time-mm.*1e6;          % dieser Prozess bearbeitet den ganzen Vektor auf einmal.
    dd=floor(time./1e4);        % dadurch kann nochmal viel Zeit gespart werden.
    time=time-dd.*1e4;          
   
    hh=floor(time./1e2);
    mi=time-hh.*1e2;            % was übrig bleibt, sind die minuten-angaben
       
   % nun kann das datenum in optimierter Form und auf einen ganzen
   % Vektor angewendet werden. Zudem muss das Muster (yyyy.mm.dd...) nicht
   % ständig neu geparst werden.
time= datenum(yyyy,mm,dd,hh,mi, 0);
   

fclose(fid);                    % entferne unnötige Daten und offene Handler aus dem Speicher
clear yyyy mm dd hh mi i s fid;
 
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
.


goMatlab ist ein Teil des goForen-Labels
goForen.de goMATLAB.de goLaTeX.de


 Impressum  | Nutzungsbedingungen  | Datenschutz  | Werbung/Mediadaten | Studentenversion | FAQ | goMatlab RSS Button RSS


Copyright © 2007 - 2019 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks
Partner: LabVIEWforum.de

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.