web-dev-qa-db-ja.com

データタイプが混在するCSVファイルをインポートする

私は数日間MATLABを使用していますが、CSVファイルをマトリックスにインポートするのが困難です。

私の問題は、CSVファイルにはほとんど文字列と整数値しか含まれていないため、csvread()が機能しないことです。 csvread()は整数値とのみ一致します。

各要素に自由にアクセスできるように、文字列を何らかの2次元配列に格納するにはどうすればよいですか?

これが私のニーズに合ったサンプルCSVです。

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

主なものは、空のセルとセル内のテキストです。ご覧のとおり、構造は異なる場合があります。

35
poeschlorn

CSVファイルに含まれるデータの列数がわかっている場合は、 textscan like Amro suggests を1回呼び出すだけが最適です溶液。

ただし、ファイル内の列の数のアプリオリがわからない場合は、次の関数でやったように、より一般的なアプローチを使用できます。最初に関数 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

質問のサンプルファイルコンテンツでこの関数を実行すると、次の結果が得られます。

>> 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'    ''    ''

結果は、セルごとに1つのフィールドを持つ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'    ''    ''

空のフィールドは NaN 値になります。

51
gnovice

あなたが投稿したサンプルを考えると、この単純なコードは仕事をするはずです:

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

次に、タイプに応じて列をフォーマットできます。たとえば、最初の列がすべて整数の場合、次のようにフォーマットできます。

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

同様に、8番目の列を16進数から10進数に変換する場合は、HEX2DECを使用できます。

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

結果のセル配列は次のようになります。

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

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  

詳細 です。

14
Andy Campbell

Xlsreadを使用します。csvファイルでも.xlsファイルと同様に機能します。 3つの出力が必要であることを指定します。

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

数値データのみを含む配列(num)、文字データのみを含む配列(char)、および.csvレイアウトと同じ形式のすべてのデータ型を含む配列(raw)を提供します。

7
Blue

ファイル交換で見つかった「CSVIMPORT」機能を使用しようとしましたか?私は自分で試したことはありませんが、テキストと数字のすべての組み合わせを処理すると主張しています。

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

6
Ghaul

ファイルの形式によっては、importdataが機能する場合があります。

文字列をセル配列に保存できます。詳細については、「doc cell」と入力してください。

4
William Payne

データセット配列を確認することをお勧めします。

データセット配列は、Statistics Toolboxに付属のデータ型です。単一のコンテナに異種データを保存するように特別に設計されています。

Statistics Toolboxのデモページには、データセット配列の機能の一部を示すいくつかのビデオが含まれています。最初のタイトルは「データセット配列の紹介」です。 2番目のタイトルは「結合の概要」です。

http://www.mathworks.com/products/statistics/demos.html

2
richard willey

入力ファイルにカンマで区切られた固定量の列があり、どの列が文字列であるかがわかっている場合は、関数を使用するのが最善かもしれません

textscan()

文字列の最大文字数まで、または区切り文字(コンマ)が見つかるまで読み取る形式を指定できることに注意してください。

1
Martin
% Assuming that the dataset is ";"-delimited and each line ends with ";"
fid = fopen('sampledata.csv');
tline = fgetl(fid);
u=sprintf('%c',tline); c=length(u);
id=findstr(u,';'); n=length(id);
data=cell(1,n);
for I=1:n
    if I==1
        data{1,I}=u(1:id(I)-1);
    else
        data{1,I}=u(id(I-1)+1:id(I)-1);
    end
end
ct=1;
while ischar(tline)
    ct=ct+1;
    tline = fgetl(fid);
    u=sprintf('%c',tline);
    id=findstr(u,';');
    if~isempty(id)
        for I=1:n
            if I==1
                data{ct,I}=u(1:id(I)-1);
            else
                data{ct,I}=u(id(I-1)+1:id(I)-1);
            end
        end
    end
end
fclose(fid);
0
Y.T.