Je travaille avec MATLAB depuis quelques jours et j'ai des difficultés à importer un fichier CSV dans une matrice.
Mon problème est que mon fichier CSV contient presque uniquement des chaînes et des valeurs entières, de sorte que csvread()
ne fonctionne pas. csvread()
s'entend uniquement avec des valeurs entières.
Comment puis-je stocker mes chaînes dans une sorte de tableau à 2 dimensions pour avoir un accès libre à chaque élément?
Voici un exemple de CSV pour mes besoins:
04;abc;def;ghj;klm;;;;;
;;;;;Test;text;0xFF;;
;;;;;asdfhsdf;dsafdsag;0x0F0F;;
L'essentiel est les cellules vides et les textes dans les cellules. Comme vous le voyez, la structure peut varier.
Dans le cas où vous savez combien de colonnes de données il y aura dans votre fichier CSV, un simple appel à textscan
comme Amro suggère sera votre meilleur Solution.
Cependant, si vous ne savez pas a priori combien de colonnes sont dans votre fichier, vous pouvez utiliser une approche plus générale comme je l'ai fait dans la fonction suivante . J'ai d'abord utilisé la fonction fgetl
pour lire chaque ligne du fichier dans un tableau de cellules. Ensuite, j'ai utilisé la fonction textscan
pour analyser chaque ligne en chaînes distinctes en utilisant un délimiteur de champ prédéfini et en traitant les champs entiers comme des chaînes pour l'instant (ils peuvent être convertis en valeurs numériques plus tard). Voici le code résultant, placé dans une fonction 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
L'exécution de cette fonction sur le contenu du fichier d'exemple de la question donne ce résultat:
>> 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' '' ''
Le résultat est un tableau de cellules de 3 sur 10 avec un champ par cellule où les champs manquants sont représentés par la chaîne vide ''
. Vous pouvez maintenant accéder à chaque cellule ou à une combinaison de cellules pour les formater à votre guise. Par exemple, si vous souhaitez modifier les champs de la première colonne de chaînes en valeurs entières, vous pouvez utiliser la fonction str2double
comme suit:
>> 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' '' ''
Notez que les champs vides entraînent des valeurs NaN
.
Compte tenu de l'exemple que vous avez publié, ce code simple devrait faire le travail:
fid = fopen('file.csv','r');
C = textscan(fid, repmat('%s',1,10), 'delimiter',';', 'CollectOutput',true);
C = C{1};
fclose(fid);
Ensuite, vous pouvez formater les colonnes en fonction de leur type. Par exemple, si la première colonne est entièrement composée d'entiers, nous pouvons la formater comme telle:
C(:,1) = num2cell( str2double(C(:,1)) )
De même, si vous souhaitez convertir la 8e colonne d'hex en décimales, vous pouvez utiliser HEX2DEC:
C(:,8) = cellfun(@hex2dec, strrep(C(:,8),'0x',''), 'UniformOutput',false);
Le tableau de cellules résultant se présente comme suit:
C =
[ 4] 'abc' 'def' 'ghj' 'klm' '' '' [] '' ''
[NaN] '' '' '' '' 'Test' 'text' [ 255] '' ''
[NaN] '' '' '' '' 'asdfhsdf' 'dsafdsag' [3855] '' ''
Dans R2013b ou version ultérieure, vous pouvez utiliser une table:
>> 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
Voici plus d'informations .
Utilisez xlsread, cela fonctionne aussi bien sur les fichiers .csv que sur les fichiers .xls. Spécifiez que vous souhaitez trois sorties:
[num char raw] = xlsread('your_filename.csv')
et il vous donnera un tableau contenant uniquement les données numériques (num), un tableau contenant uniquement les données de caractère (char) et un tableau qui contient tous les types de données dans le même format que la disposition .csv (brut).
Avez-vous essayé d'utiliser la fonction "CSVIMPORT" trouvée dans l'échange de fichiers? Je ne l'ai pas essayé moi-même, mais il prétend gérer toutes les combinaisons de texte et de chiffres.
http://www.mathworks.com/matlabcentral/fileexchange/23573-csvimport
Selon le format de votre fichier, importdata peut fonctionner.
Vous pouvez stocker des chaînes dans un tableau de cellules. Tapez "doc cell" pour plus d'informations.
Je recommande de regarder le tableau de l'ensemble de données.
Le tableau de l'ensemble de données est un type de données fourni avec Statistics Toolbox. Il est spécialement conçu pour stocker des données hétérogènes dans un seul conteneur.
La page de démonstration de Statistics Toolbox contient quelques vidéos qui montrent certaines des fonctionnalités du tableau de jeux de données. Le premier est intitulé "Une introduction aux tableaux de jeux de données". Le second est intitulé "Une introduction aux jointures".
Si votre fichier d'entrée contient un nombre fixe de colonnes séparées par des virgules et que vous savez dans quelles colonnes se trouvent les chaînes, il est préférable d'utiliser la fonction
textscan()
Notez que vous pouvez spécifier un format dans lequel vous lisez jusqu'à un nombre maximum de caractères dans la chaîne ou jusqu'à ce qu'un délimiteur (virgule) soit trouvé.
% 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);