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ć.
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.
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] '' ''
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 .
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).
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
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.
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".
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).
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);
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