2016-05-26 5 views
1

Ich habe Matlab verwendet, um .txt Dateien zu erstellen, die 3 Spalten haben, die durch Registerkarten (Zeichenfolge, Float, Float) und variierende Anzahl der Zeilen getrennt sind.Wie importiere ich Daten aus einer Datei in variable Arrays? (Matlab)

Ich versuche, jede dieser 3 Spalten von Daten in 3 verschiedenen Variablen zu lesen. Hier ist mein Code:

fileId = fopen('file.txt'); 

% Storing columns from txt file into appropriate compartment data arrays 
compartment_name = textscan(fileId,'%s%*f%*f','Delimiter','\t'); % column of strings 
compartment_length = textscan(fileId,'%*s%f%*f','Delimiter','\t'); % column of doubles 
compartment_diameter = textscan(fileId,'%*s%*f%f','Delimiter','\t'); % column of doubles 

fclose('file.txt'); 

erhalte ich die richtigen Daten für compartment_name (1x1 Zelle, die 106x1-Zellen (von denen jeder ein String)), aber beide compartment_length und compartment_diameter ein leeres 1x1 zurückkehren Zelle, die eine 0x1 Doppel enthält.

Irgendwelche Gedanken?

Auch - gibt es eine einfache Möglichkeit für mich, die 1x1-Zellen in ein Array zu konvertieren? zB für compartment_name, wäre es ein Array von 1x106 Strings?

+0

Ich denke, das Problem kann sein, dass die Dateipositionsanzeige nach dem ersten Textscan am Ende der Datei geparkt wird. Versuchen Sie 'fseek (fileId, 0, 'bof')', um den Indikator zwischen den Lesevorgängen an den Anfang der Datei zu verschieben. – jgrant

Antwort

1

Da @jgrant notiert in a comment, ist das Problem, dass Sie die Dateipositionsanzeige an den Anfang der Datei zurücksetzen müssen, wenn Sie Teile Ihrer Datei erneut lesen möchten.

Ich kann nicht wirklich sehen, warum Sie textscan dreimal zu nennen sind versucht, den Grund, dass die Ausgabe von textscan ist eine Zelle genau ist, dass Sie einen einzigen Aufruf kann es tun, dann die Ausgabespalten trennen:

tmpcell = textscan(fileId,'%s%f%f','Delimiter','\t'); % column of strings 

compartment_name = tmpcell{1}; 
compartment_length = tmpcell{2}; 
compartment_diameter = tmpcell{3}; 

% or if you want to be fancy about it: 
%[compartment_name, compartment_length, compartment_diameter] = tmpcell{:}; 

Der Grund, warum ich diese Antwort zu schreiben up ist Ihre letzte Bemerkung:

auch - ist es eine einfache Möglichkeit für mich, die 1x1-Zellen in eine Array-Format konvertieren? zB für compartment_name, wäre es ein Array von 1x106 Strings?

Dies deutet auf eine Verwechslung von Zeichenfolgen in MATLAB hin. In MATLAB sind Strings im Wesentlichen Arrays von Ganzzahlen. Sie können selbst sehen dies an einer Schnur, jede Art von Rechenoperation durchführen:

>> tmpstring = 'asdf' 

tmpstring = 

asdf 

>> tmpstring*1 

ans = 

    97 115 100 102 

Die Zahlen Sie die ASCII-Darstellungen der Zeichen in der Zeichenfolge sehen sind. Das funktioniert auch umgekehrt: Sie können einen String aufbauen, indem Sie Integer in ein Array einfügen. Als in der Tat für alle Absichten und Zwecke reiht sind Integer Arrays:

>> isequal([97 115 100 102],'asdf') 

ans = 

    1 

Dies impliziert auch einige Einschränkungen für Streicher in MATLAB. Was Ihre Frage betrifft, ist, dass Sie nicht einfach ein Array von Strings erstellen können. Das wäre genau String-Verkettung: Wenn sowohl string1 als auch string2 nur Integer-Arrays sind, dann ist [string1, string2] die Verkettung der beiden Strings.

Sie können dann denken, Strings horizontal zu stapeln, mit [string1; string2]. Nun, das funktioniert genau so, wie es für zwei Integer-Arrays funktionieren würde: Sie können dies nur tun, wenn die Strings die gleiche Länge haben (Länge bedeutet jetzt size(string1,2)).Im allgemeinen Fall können Sie also nur Strings zusammen in einem inhomogenen Container, d. H. Zellen in MATLAB, speichern. Sobald Sie Zellen haben, können Ihre Elemente jeden Typ und jede Form haben, so dass Sie einfach Strings beliebiger Länge zusammenschieben können, vertikal oder horizontal gestapelt, wie Sie es auch mögen.

So betrachten textscan. Sie müssen diese Funktion implementieren, die Daten zurückgibt, die aus einer Datei gelesen werden. Die Daten können sowohl numerisch als auch Zeichenfolgen sein. Wie geht's? Genau das, was textscan tut: Rückgabe numerische Spalten als Arrays (da jede Zeile hat eine einzige skalare Daten), und geben Sie Zeichenfolgen als Zellen (da jede Zeile enthält eine Zeichenfolge, d. H. Ein Vektor an sich!). Sie könnte Stapel die Zeichenfolgen horizontal, aber das funktioniert nur, wenn jede Zeile in der angegebenen Spalte die gleiche Anzahl von Zeichen enthält, die offensichtlich nicht angenommen oder vorgeschrieben werden sollte. Sie können immer noch die Zeichenfolgen auf das längste Element auffüllen und ein gestapeltes Zeichenarray zurückgeben, aber dies würde in den meisten praktischen Anwendungen unnötigen Overhead einführen. (Randnotiz: textscan gibt einen Zellenzeilenvektor als Ausgabe zurück, wobei jedes Zellenelement die vollständigen Daten in der angegebenen Spalte enthält. Für numerische Spalten ist diese "vollständige Daten" ein Array-Spaltenvektor und für String-Spalten eine Zellenspalte Vektor.)

So ist es sinnvoll, dass textscan seine String-Spalten als Zellen zurückgibt. Sie können Ihre Strings trotzdem in ein 2d String-Array stapeln, wenn Sie möchten, aber in den meisten Fällen ist das nicht wirklich praktisch. Es hängt wirklich von Ihrer Anwendung ab.

Ein minimales Beispiel: bedenkt, dass tmp.inp enthält

asf 3 4 
asdg 2 3 
asd 1 4 

Jetzt

>> fid=fopen('tmp.inp','r'); outcell=textscan(fid,'%s%f%f'), fclose(fid); 

outcell = 

    {3x1 cell} [3x1 double] [3x1 double] 

kommt die Tatsache zeigt, dass der Ausgang der outcell eine Zelle Zeilenvektor ist, auf eine Säule jedes Element liest entsprechende aus der Datei. Die eckigen Klammern um Spalte 2 und 3 zeigen an, dass diese Zellenelemente (nämlich outcell{2} und outcell{3}, nicht zu verwechseln mit outcell(2) und outcell(3)) numerische Arrays sind. Das erste Element ist jedoch eine Zelle Spaltenvektor:

>> outcell{1} 

ans = 

    'asf' 
    'asdg' 
    'asd' 

Die Tatsache, dass die Ausgabe mit Anführungszeichen gedruckt wird auf jede Zeile zeigt an, dass diese getrennte Zeichenfolgen in einer Zelle enthalten ist, aber Sie können dies auch sagen aus

>> whos ans 
    Name  Size   Bytes Class Attributes 

    ans  3x1    356 cell    

Nun, wie ich schon sagte, können Sie Ihre Spalten stapeln auf dem jeweils anderen entscheiden, brauchen Sie nur char() auf Ihrem Handy anrufen:

>> char(outcell{1}) 

ans = 

asf 
asdg 
asd 

>> whos ans 
    Name  Size   Bytes Class Attributes 

    ans  3x4    24 char    

Beachten Sie das Fehlen von Anführungszeichen in der automatischen Ausgabe und die Klasse/Größe der Ausgabe. Die Größe 3x4 wurde ermöglicht, indem alle Zeilen auf die Länge der längsten Zeichenfolge aufgefüllt wurden, d. H. 4. Folglich endet die erste und dritte Zeile der Ausgabe mit einem Leerzeichen (dies ist gemeint, wenn die Zeichenfolgen erhalten).

Wenn Sie nicht über diese Polsterung durchführen, können Sie einfach Ihre Saiten lesen, wie die Zellelemente verweisen sie sind:

>> outcell{1}{3} 

ans = 

asd 

Oder durch die Variable zu speichern, wie Sie wollten ursprünglich:

>> compartment_name=outcell{1} 

compartment_name = 

    'asf' 
    'asdg' 
    'asd' 

>> compartment_name{3} 

ans = 

asd 
Verwandte Themen