30 votos

Importar un archivo CSV con los tipos de datos mixtos

Estoy trabajando con MATLAB para unos días y estoy teniendo dificultades para importar un archivo CSV-a una matriz.

Mi problema es que mi CSV-archivo contiene casi las únicas Cadenas y algunos valores enteros, por lo que csvread() no funciona. csvread() sólo se lleva bien con valores enteros.

¿Cómo puedo almacenar mis cadenas en algún tipo de 2-dimensiones de la matriz a tener libre acceso a cada elemento?

He aquí un CSV de ejemplo para mis necesidades:

04;abc;def;ghj;klm;;;;;
;;;;;Test;text;0xFF;;
;;;;;asdfhsdf;dsafdsag;0x0F0F;;

Lo principal son las celdas vacías y los textos dentro de las células. Como se puede ver, la estructura puede variar.

40voto

gnovice Puntos 70970

Editado ahora que la cuestión ha sido actualizado con un ejemplo de archivo de entrada...

Para el caso cuando usted sabe cuántas columnas de datos que habrá en el archivo CSV, una simple llamada a TEXTSCAN como Amro sugiere que será su mejor solución.

Sin embargo, si usted no sabe a priori cuántas columnas se encuentran en el archivo, puede utilizar un enfoque más general, como lo hice en la siguiente función. La primera vez que utiliza la función FGETL para leer cada línea del archivo en una celda de la matriz. Luego usé la función TEXTSCAN para analizar cada línea en cadenas independientes utilizando un predefinidos delimitador de campo y el tratamiento de los campos de entero como cadenas de ahora (que puede ser convertido a valores numéricos más adelante). Aquí está el código resultante, se coloca en una función read_mixed_csv:

function lineArray = read_mixed_csv(fileName,delimiter)
  fid = fopen(fileName,'r');   %# Open the file
  lineArray = cell(100,1);     %# Preallocate a cell array (ideally slightly
                               %#   larger than is needed)
  lineIndex = 1;               %# Index of cell to place the next line in
  nextLine = fgetl(fid);       %# Read the first line from the file
  while ~isequal(nextLine,-1)         %# Loop while not at the end of the file
    lineArray{lineIndex} = nextLine;  %# Add the line to the cell array
    lineIndex = lineIndex+1;          %# Increment the line index
    nextLine = fgetl(fid);            %# Read the next line from the file
  end
  fclose(fid);                 %# Close the file
  lineArray = lineArray(1:lineIndex-1);  %# Remove empty cells, if needed
  for iLine = 1:lineIndex-1              %# Loop over lines
    lineData = textscan(lineArray{iLine},'%s',...  %# Read strings
                        'Delimiter',delimiter);
    lineData = lineData{1};              %# Remove cell encapsulation
    if strcmp(lineArray{iLine}(end),delimiter)  %# Account for when the line
      lineData{end+1} = '';                     %#   ends with a delimiter
    end
    lineArray(iLine,1:numel(lineData)) = lineData;  %# Overwrite line data
  end
end

Ejecutando esta función en el archivo de ejemplo el contenido de la pregunta que da este resultado:

>> data = read_mixed_csv('myfile.csv',';')

data = 

  Columns 1 through 7

    '04'    'abc'    'def'    'ghj'    'klm'    ''            ''        
    ''      ''       ''       ''       ''       'Test'        'text'    
    ''      ''       ''       ''       ''       'asdfhsdf'    'dsafdsag'

  Columns 8 through 10

    ''          ''    ''
    '0xFF'      ''    ''
    '0x0F0F'    ''    ''

El resultado es una de 3-por-10 matriz de células con un campo por celda en los campos que faltan están representados por la cadena vacía ''. Ahora usted puede tener acceso a cada celda o una combinación de las células para darles formato como te gusta. Por ejemplo, si desea cambiar los campos en la primera columna de cadenas de valores enteros, puede utilizar la función STR2DOUBLE de la siguiente manera:

>> data(:,1) = cellfun(@(s) {str2double(s)},data(:,1))

data = 

  Columns 1 through 7

    [  4]    'abc'    'def'    'ghj'    'klm'    ''            ''        
    [NaN]    ''       ''       ''       ''       'Test'        'text'    
    [NaN]    ''       ''       ''       ''       'asdfhsdf'    'dsafdsag'

  Columns 8 through 10

    ''          ''    ''
    '0xFF'      ''    ''
    '0x0F0F'    ''    ''

Tenga en cuenta que los campos vacíos resultados en NaN valores.

16voto

Amro Puntos 72743

Teniendo en cuenta la muestra que se registra, este simple código debe hacer el trabajo:

fid = fopen('file.csv','r');
C = textscan(fid, repmat('%s',1,10), 'delimiter',';', 'CollectOutput',true);
C = C{1};
fclose(fid);

Entonces podría formatear las columnas según su tipo. Por ejemplo si la primera columna es todos enteros, podemos formatearlo como tal:

C(:,1) = num2cell( str2double(C(:,1)) )

Del mismo modo, si desea convertir la columna 8 de hex a decimales, puede utilizar HEX2DEC:

C(:,8) = cellfun(@hex2dec, strrep(C(:,8),'0x',''), 'UniformOutput',false);

La matriz de la célula resultante es como sigue:

C = 
    [  4]    'abc'    'def'    'ghj'    'klm'    ''            ''                []    ''    ''
    [NaN]    ''       ''       ''       ''       'Test'        'text'        [ 255]    ''    ''
    [NaN]    ''       ''       ''       ''       'asdfhsdf'    'dsafdsag'    [3855]    ''    ''

6voto

Ghaul Puntos 2871

¿Has probado a usar la función "CSVIMPORT" se encuentra en el intercambio de archivos? Yo no he intentado hacerlo yo mismo, pero que pretende manejar todas las combinaciones de texto y números.

http://www.mathworks.com/matlabcentral/fileexchange/23573-csvimport

5voto

Blue Puntos 41

Utilice xlsread, funciona igual de bien en archivos .csv que en archivos .xls. Especificar que quiere tres salidas:

[num char raw] = xlsread('your_filename.csv')

y le dará una matriz que contiene sólo los datos numéricos (num), una matriz que contiene los datos de carácter (char) y una matriz que contiene todos los tipos de datos en el mismo formato que el diseño de .csv (en bruto).

4voto

William Payne Puntos 430

Dependiendo del formato del archivo, importdata podría funcionar.

Cadenas se pueden almacenar en una matriz celular. Tipo «célula doc» para obtener más información.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X