Especificar dinámicamente el tamaño del número de coma flotante en una instrucción sscanf con función cerrada
Tengo un archivo de datos estructurados que consiste en líneas de encabezado intercaladas con bloques de datos. Estoy leyendo cada bloque de datos (como lo define la línea de encabezado) en una celda separada de una matriz de celdas. Por ejemplo, supongamos que después de cargar los datos contextscan
Tengo una matriz de celdasx
y una variedad de índices de líneas de encabezado y EOF (headerIdx
) de la siguiente forma:
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];
Luego intento extraer cada bloque de datos debajo de una línea de encabezado en un elemento separado de una matriz de celdas usandosscanf
ystr2mat
(como lo sugiereesta publicación) Inicialmente, este enfoque falló porque los elementos dentro de un bloque de datos dado eran de diferente longitud. Esto se puede resolver incluyendo una bandera numérica para'%f'
argumento para ayudarsscanf
saber dónde delimitar los datos de entrada (como lo sugiereesta publicación) Entonces se puede usar una estrategia como la siguiente para efectuar la conversión de datos estructurados a una matriz de celdas de matrices dobles específicas de bloque:
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);
El indicador numérico de la cadena de formato se puede establecer en algo arbitrariamente grande para abarcar todos los datos, o se puede establecer en una base específica de bloque como lo hice en el ejemplo anterior. El último enfoque lleva a una evaluación redundante destr2mat
(una vez para la entrada asscanf
y una vez para la entrada a la'%f'
generador de cuerdas ¿Se puede evitar esta redundancia sin usar sentencias de bucle que almacenen la salida delstr2mat
comando en una variable temporal? Tenga en cuenta que uno no puede simplemente tomar la salida de lasize
comando aplicado a la salida destr2mat(x).'
en todo el conjunto de datos porque las líneas de encabezado generalmente serán las líneas con el mayor número de caracteres.
Finalmente, he construido elx
matriz anterior para reflejar el hecho de que algunos bloques de datos pueden tener una precisión diferente que otros bloques. Esta es la razón para establecer la cadena de formato de una manera específica de bloque. Mi prueba ha demostrado que a pesar de la construcción precisa de una cadena de formato específica de bloque (['%' num2str(size(str2mat(x(headerIdx(n)+1:headerIdx(n+1)-1)).',1)) 'f']
), los datos en todos los elementos de la matriz de celdas resultante (extracted_data
) se ven obligados a tener la misma precisión (ver más abajo). ¿Por qué es este el caso y cómo se puede corregir?
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