导入具有混合数据类型的CSV文件

poe*_*orn 35 csv import file-io matlab parsing

我正在使用MATLAB几天,我很难将CSV文件导入矩阵.

我的问题是我的CSV文件几乎只包含字符串和一些整数值,所以这csvread()不起作用.csvread()只与整数值相关.

如何将我的字符串存储在某种二维数组中,以便可以自由访问每个元素?

以下是我需要的示例CSV:

04;abc;def;ghj;klm;;;;;
;;;;;Test;text;0xFF;;
;;;;;asdfhsdf;dsafdsag;0x0F0F;;
Run Code Online (Sandbox Code Playgroud)

主要是空单元格和单元格内的文本.如您所见,结构可能会有所不同.

gno*_*ice 51

对于您知道CSV文件中将包含多少列数据的情况,一个textscanAmro建议的简单调用将是您的最佳解决方案.

但是,如果您事先不知道文件中有多少列,则可以使用更常规的方法,就像我在以下函数中所做的那样.我首先使用该函数fgetl将文件的每一行读入单元格数组.然后我使用函数textscan使用预定义的字段分隔符将每一行解析为单独的字符串,并将整数字段视为现在的字符串(稍后可以将它们转换为数值).以下是生成的代码,放在一个函数中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
Run Code Online (Sandbox Code Playgroud)

在问题的示例文件内容上运行此函数会得到以下结果:

>> 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'    ''    ''
Run Code Online (Sandbox Code Playgroud)

结果是一个3乘10的单元阵列,每个单元有一个字段,其中缺少的字段由空字符串表示''.现在,您可以访问每个单元格或单元格组合,以根据需要对其进行格式化.例如,如果要将第一列中的字段从字符串更改为整数值,可以使用以下函数str2double:

>> 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'    ''    ''
Run Code Online (Sandbox Code Playgroud)

请注意,空字段会产生NaN值.


Amr*_*mro 20

鉴于您发布的样本,这个简单的代码应该完成这项工作:

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

然后,您可以根据类型格式化列.例如,如果第一列是全部整数,我们可以将其格式化为:

C(:,1) = num2cell( str2double(C(:,1)) )
Run Code Online (Sandbox Code Playgroud)

同样,如果您希望将第8列从十六进制转换为十进制,则可以使用HEX2DEC:

C(:,8) = cellfun(@hex2dec, strrep(C(:,8),'0x',''), 'UniformOutput',false);
Run Code Online (Sandbox Code Playgroud)

生成的单元格数组如下所示:

C = 
    [  4]    'abc'    'def'    'ghj'    'klm'    ''            ''                []    ''    ''
    [NaN]    ''       ''       ''       ''       'Test'        'text'        [ 255]    ''    ''
    [NaN]    ''       ''       ''       ''       'asdfhsdf'    'dsafdsag'    [3855]    ''    ''
Run Code Online (Sandbox Code Playgroud)


And*_*ell 14

在R2013b或更高版本中,您可以使用表格:

>> table = readtable('myfile.txt','Delimiter',';','ReadVariableNames',false)
>> table = 

    Var1    Var2     Var3     Var4     Var5        Var6          Var7         Var8      Var9    Var10
    ____    _____    _____    _____    _____    __________    __________    ________    ____    _____

      4     'abc'    'def'    'ghj'    'klm'    ''            ''            ''          NaN     NaN  
    NaN     ''       ''       ''       ''       'Test'        'text'        '0xFF'      NaN     NaN  
    NaN     ''       ''       ''       ''       'asdfhsdf'    'dsafdsag'    '0x0F0F'    NaN     NaN  
Run Code Online (Sandbox Code Playgroud)

这是更多信息.


小智 7

使用xlsread,它在.csv文件上的效果与在.xls文件上的效果一样.指定您想要三个输出:

[num char raw] = xlsread('your_filename.csv')
Run Code Online (Sandbox Code Playgroud)

它将为您提供一个仅包含数字数据(num)的数组,一个仅包含字符数据(char)的数组,以及一个包含与.csv布局(原始)格式相同的所有数据类型的数组.


Gha*_*aul 6

您是否尝试使用文件交换中的"CSVIMPORT"功能?我自己没有尝试过,但它声称处理文本和数字的所有组合.

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