Gleitkommazahlgröße in einer funktionsumschlossenen sscanf-Anweisung dynamisch angeben
Ich habe eine strukturierte Datendatei, die aus Kopfzeilen besteht, die mit Datenblöcken durchsetzt sind. Ich lese jeden Datenblock (wie durch die Kopfzeile definiert) in eine separate Zelle eines Zellenarrays. Angenommen, nach dem Laden der Daten mittextscan
Ich habe ein Zellenarrayx
und ein Array von Indizes von Kopfzeilen und EOF (headerIdx
) des folgenden Formulars:
x={'header line 1';'98.78743';'99.39717';'99.93578';'100.40125';'100.79166';'101.10525';'101.34037';'101.49553';'101.56939';'101.56072';'101.4685';'101.29184';'101.03002';'100.68249';'header line 2';'100.24887';'99.72897';'99.12274';'98.43036';'97.65215';'96.78864';'95.84054';'header line 3';'3.2';'4.31';'2.7';'4.6';'9.3'};
headerIdx=[1;16;24;30];
Ich versuche dann, jeden Datenblock unter einer Kopfzeile in ein separates Element eines Zellenarrays zu extrahierensscanf
undstr2mat
(wie vorgeschlagen vondieser Beitrag). Anfangs schlug dieser Ansatz fehl, weil die Elemente innerhalb eines bestimmten Datenblocks unterschiedlich lang waren. Dies kann durch Einfügen eines numerischen Flags für das gelöst werden'%f'
Argument zu helfensscanf
wissen, wo die Eingabedaten abzugrenzen sind (wie von vorgeschlagen)dieser Beitrag). Man kann dann eine Strategie wie die folgende anwenden, um die Umwandlung strukturierter Daten in ein Zellenfeld blockspezifischer Doppelfelder zu bewirken:
extract_data = @(n) sscanf(str2mat(x(headerIdx(n)+1:headerIdx(n+1)-1)).',['%' num2str(size(str2mat(x(headerIdx(n)+1:headerIdx(n+1)-1)).',1)) 'f']);
extracted_data = arrayfun(extract_data,1:numel(headerIdx)-1,'UniformOutput',false);
Das numerische Flag der Formatzeichenfolge kann entweder auf eine beliebige Größe festgelegt werden, um alle Daten zu umfassen, oder es kann blockspezifisch festgelegt werden, wie im obigen Beispiel. Letzterer Ansatz führt zu einer redundanten Auswertung vonstr2mat
(einmal für die Eingabe ansscanf
und einmal für die Eingabe in die'%f'
String-Generator. Kann diese Redundanz vermieden werden, ohne dass Schleifenanweisungen verwendet werden, in denen die Ausgabe von gespeichert wird?str2mat
Befehl in einer temporären Variablen? Beachten Sie, dass man nicht einfach die Ausgabe dessize
Befehl, der auf die Ausgabe von angewendet wirdstr2mat(x).'
auf dem gesamten Datensatz, da die Kopfzeilen im Allgemeinen die Zeilen mit der größten Anzahl von Zeichen sein werden.
Endlich habe ich das gebautx
obige Matrix, um die Tatsache widerzuspiegeln, dass einige Datenblöcke eine andere Genauigkeit aufweisen können als andere Blöcke. Dies ist der Grund, den Formatstring blockspezifisch zu setzen. Meine Tests haben gezeigt, dass trotz genauer Konstruktion eines blockspezifischen Formatstrings (['%' num2str(size(str2mat(x(headerIdx(n)+1:headerIdx(n+1)-1)).',1)) 'f']
), die Daten in allen Elementen des resultierenden Zellenarrays (extracted_data
) sind letztendlich gezwungen, die gleiche Präzision zu haben (siehe unten). Warum ist das so und wie kann es korrigiert werden?
extracted_data{:}
ans =
98.7874
99.3972
99.9358
100.4013
100.7917
101.1052
101.3404
101.4955
101.5694
101.5607
101.4685
101.2918
101.0300
100.6825
ans =
100.2489
99.7290
99.1227
98.4304
97.6522
96.7886
95.8405
ans =
3.2000
4.3100
2.7000
4.6000
9.3000