Importuj plik CSV z mieszanymi typami danych

Pracuję z MATLABEM przez kilka dni i mam problemy z zaimportowaniem pliku CSV do matrycy.

Mój problem polega na tym, że mój plik CSV zawiera prawie tylko ciągi znaków i niektóre wartości całkowite, więc csvread() nie działa. csvread() dogaduje się tylko z wartościami całkowitymi.

Jak mogę przechowywać moje ciągi w jakiejś dwuwymiarowej tablicy, aby mieć swobodny dostęp do każdego elementu?

Oto przykładowy CSV dla moich potrzeb:

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

Najważniejsze są puste komórki i teksty w komórkach. Jak widzisz, struktura może się różnić.

Author: chappjc, 2011-01-20

9 answers

W przypadku, gdy wiesz, ile kolumn danych będzie w Twoim pliku CSV, jedno proste wywołanie do textscan tak jak AMRO sugeruje będzie twoim najlepszym rozwiązaniem.

Jeśli jednak nie wiesz a priori ile kolumn znajduje się w Twoim pliku, możesz użyć bardziej ogólnego podejścia, jak to zrobiłem w poniższej funkcji. Po raz pierwszy użyłem funkcji fgetl aby odczytać każdą linię pliku do tablicy komórki. Następnie użyłem funkcji textscan na parsuje każdą linię do osobnych łańcuchów używając predefiniowanego ogranicznika pól i traktując pola całkowite jako ciągi znaków na razie (można je później przekonwertować na wartości liczbowe). Oto kod wynikowy, umieszczony w funkcji 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

Uruchomienie tej funkcji na przykładowej zawartości pliku z pytania daje taki wynik:

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

Wynikiem jest tablica komórek 3 na 10 z jednym polem na komórkę, gdzie brakujące pola są reprezentowane przez pusty łańcuch ''. Teraz możesz uzyskać dostęp każda komórka lub Kombinacja komórek, aby sformatować je tak, jak chcesz. Na przykład, jeśli chcesz zmienić pola w pierwszej kolumnie z wartości ciągów na wartości całkowite, możesz użyć funkcji str2double Jak Następuje:

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

Zauważ, że puste pola powodują NaN wartości.

 51
Author: gnovice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-26 18:57:51

Biorąc pod uwagę próbkę, którą opublikowałeś, ten prosty kod powinien wykonać zadanie:

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

Następnie możesz sformatować kolumny według ich typu. Na przykład, jeśli pierwsza kolumna to wszystkie liczby całkowite, możemy sformatować ją w taki sposób:

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

Podobnie, jeśli chcesz przekonwertować ósmą kolumnę z hex na dziesiętne, możesz użyć HEX2DEC:

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

Wynikowa tablica komórek wygląda następująco:

C = 
    [  4]    'abc'    'def'    'ghj'    'klm'    ''            ''                []    ''    ''
    [NaN]    ''       ''       ''       ''       'Test'        'text'        [ 255]    ''    ''
    [NaN]    ''       ''       ''       ''       'asdfhsdf'    'dsafdsag'    [3855]    ''    ''
 20
Author: Amro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-27 15:37:17

W R2013b lub nowszym możesz użyć tabeli:

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

Oto więcej informacji .

 14
Author: Andy Campbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-28 18:26:20

Użyj xlsread, działa równie dobrze na .pliki csv jak to robi na .pliki xls. Określ, że chcesz mieć trzy wyjścia:

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

I da ci tablicę zawierającą tylko dane liczbowe( num), tablicę zawierającą tylko dane znakowe (char) oraz tablicę zawierającą wszystkie typy danych w tym samym formacie co.układ csv (raw).

 7
Author: Blue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-04 23:31:22

Czy próbowałeś użyć funkcji "CSVIMPORT" znalezionej w wymianie plików? Sam nie próbowałem, ale twierdzi, że obsługuje wszystkie kombinacje tekstu i liczb.

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

 6
Author: Ghaul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-25 09:22:04

W zależności od formatu pliku, importdata może działać.

Możesz przechowywać łańcuchy w tablicy komórek. Wpisz "komórka doc", aby uzyskać więcej informacji.

 4
Author: William Payne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-20 16:09:09

Polecam spojrzeć na tablicę dataset.

Tablica dataset jest typem danych, który jest dostarczany z zestawem narzędzi statystycznych. Jest specjalnie zaprojektowany do przechowywania hetrogennych danych w jednym pojemniku.

The Statistics Toolbox Demo page zawiera kilka vidoes, które pokazują niektóre z funkcji dataset array. Pierwszy z nich nosi tytuł "Wprowadzenie do tablic zestawów danych". Drugi nosi tytuł " Wprowadzenie do Dołącza".

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

 2
Author: richard willey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-21 18:59:38

Jeśli plik wejściowy ma stałą ilość kolumn oddzielonych przecinkami i wiesz, w których kolumnach są ciągi znaków, najlepiej użyć funkcji

textscan()

Zauważ, że możesz określić format, w którym można odczytać maksymalnie maksymalną liczbę znaków w łańcuchu lub do momentu znalezienia ogranicznika (przecinka).

 1
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-04 23:31:52
% 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
Author: Y.T.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-28 12:02:33