我正在使用MATLAB几天,而且我很难将CSV文件导入矩阵。
我的问题是我的CSV文件几乎只包含字符串和一些整数值,因此csvread()
不起作用。 csvread()
仅与整数值相关。
如何将我的字符串存储在某种二维数组中,以便可以自由访问每个元素?
以下是符合我需求的示例CSV:
04;abc;def;ghj;klm;;;;;
;;;;;Test;text;0xFF;;
;;;;;asdfhsdf;dsafdsag;0x0F0F;;
主要是空单元格和单元格内的文本。 如您所见,结构可能会有所不同。
答案 0 :(得分:51)
如果您知道CSV文件中将包含多少列数据,则只需拨打textscan
Amro suggests就可以轻松调用fgetl
。
但是,如果您不知道先验文件中有多少列,您可以使用更常规的方法,就像我在以下函数中所做的那样。我首先使用函数textscan
将文件的每一行读入单元格数组。然后我使用函数str2double
使用预定义的字段分隔符将每一行解析为单独的字符串,并将整数字段视为现在的字符串(稍后可将它们转换为数值)。以下是生成的代码,放在函数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' '' ''
结果是一个3乘10的单元阵列,每个单元格有一个字段,其中缺少的字段由空字符串''
表示。现在,您可以访问每个单元格或单元格组合,以根据需要对其进行格式化。例如,如果要将第一列中的字段从字符串更改为整数值,可以使用函数NaN
,如下所示:
>> 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' '' ''
请注意,空字段会产生{{3}}个值。
答案 1 :(得分:20)
鉴于你发布的样本,这个简单的代码应该完成这项工作:
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列从十六进制转换为十进制,则可以使用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] '' ''
答案 2 :(得分: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
这是more info。
答案 3 :(得分:7)
使用xlsread,它在.csv文件上的效果与在.xls文件上的效果一样。指定您想要三个输出:
[num char raw] = xlsread('your_filename.csv')
它将为您提供仅包含数字数据(num)的数组,仅包含字符数据(char)的数组以及包含与.csv布局(原始)格式相同的所有数据类型的数组。
答案 4 :(得分:6)
您是否尝试过使用文件交换中的“CSVIMPORT”功能?我自己没有尝试过,但它声称要处理文本和数字的所有组合。
http://www.mathworks.com/matlabcentral/fileexchange/23573-csvimport
答案 5 :(得分:4)
根据文件的格式, importdata 可能有效。
您可以将字符串存储在单元格数组中。输入“doc cell”以获取更多信息。
答案 6 :(得分:2)
我建议查看数据集数组。
数据集数组是Statistics Toolbox附带的数据类型。 它专门用于将异构数据存储在单个容器中。
Statistics Toolbox演示页面包含几个显示一些数据集阵列功能的视频。第一个标题为“数据集阵列简介”。第二个标题是“加入简介”。
答案 7 :(得分:1)
如果您的输入文件具有以逗号分隔的固定数量的列,并且您知道哪些列是字符串,则最好使用该函数
textscan()
请注意,您可以指定一种格式,在该格式中,您可以读取字符串中的最大字符数,或者直到找到分隔符(逗号)。
答案 8 :(得分:0)
% 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);