Arrays MATLAB:使用textscan并在矩阵中转换单元阵列
我有一个大的csv文件(大约100万行),其中包含以下结构的选项数据(内容已更改): 我已使用以下命令成功导入测试文件:Arrays MATLAB:使用textscan并在矩阵中转换单元阵列,arrays,matlab,csv,cell,textscan,Arrays,Matlab,Csv,Cell,Textscan,我有一个大的csv文件(大约100万行),其中包含以下结构的选项数据(内容已更改): 我已使用以下命令成功导入测试文件: ftest = fopen('test.csv'); C = textscan(ftest,'%f %s %f %f %f %f %f %f %s %s %f %f','Headerlines',1,'Delimiter',','); fclose(ftest); 然而,C是一个单元数组,这使得在matlab中处理文件内容变得更加困难。将其作为“常规”数组更容易(请原谅我不
ftest = fopen('test.csv');
C = textscan(ftest,'%f %s %f %f %f %f %f %f %s %s %f %f','Headerlines',1,'Delimiter',',');
fclose(ftest);
然而,C是一个单元数组,这使得在matlab中处理文件内容变得更加困难。将其作为“常规”数组更容易(请原谅我不知道正确的命名法,我刚刚开始使用matlab)
如果我输出C,我得到:
Columns 1 through 6
[2x1 double] {2x1 cell} [2x1 double] [2x1 double] [2x1 double] [2x1 double]
Columns 7 through 12
[2x1 double] [2x1 double] {2x1 cell} {2x1 cell} [2x1 double] [2x1 double]
所以在C单元数组中,有数组和单元数组-数组代表数字,单元数组代表字符串。如果我试图检查元素(1,2),我必须使用C{1}(2),但是如果我想检查元素(2,2),我必须使用C{2}{2}。理想情况下,我希望以C(1,2)和C(2,2)的形式访问。
问题是,我该怎么做
我已经搜索了解决方案并找到了CellsMat,但它只有在所有内容都是数字的情况下才有效(我想)。我找到了这个解决方案:但是horzcat检索到一个错误,我相信这可能是由于同样的问题
提前感谢您的时间。由于您有一个同时包含数字和字符数据的数组,您想要的是不可能的(相信我,这也不切实际) 在数值数组中引用单个数字不同于引用整个字符串。这是无法逃避的,也不应该逃避:你对待鲜花的方式与对待他人的方式不同(我当然希望如此) 在MATLAB中,字符串是一个普通数组,不同的是数组的每个条目并不代表一个数字,而是一个字符。引用单个字符与引用数组中的数字相同:
>> a = 'my string'
>> a(4)
ans =
s
>> a+0 % cast to double to show the "true character" of strings
ans =
109 121 32 115 116 114 105 110 103
但是,textscan
假定(正确地说)您不希望这样做,而是希望从文件中提取整个字符串。整个字符串应该以不同的方式引用,以表明您指的是整个字符串而不是单个字符
我认为,如果将textscan
的结果拆分为普通数字数组和字符串单元格数组,您会发现这一切更加直观,如下所示:
% load the data
ftest = fopen('test.csv');
C = textscan(ftest,...
'%f %s %f %f %f %f %f %f %s %s %f %f',...
'collectoutput', true,...
'Delimiter',',\n');
fclose(ftest);
% split into numeric and char arrays
numeric = [C{[1 3 5]}]
alpha = [C{[2 4]}]
引用numeric
中的数据遵循与任何普通数组相同的规则,引用alpha
中的字符串遵循正常的单元格引用规则(如alpha{2,1}
中获得'03/05/1986'
)
编辑根据您的评论,您希望按照以下方式进行转换:
% Read the data
fid = fopen('test.csv', 'r');
C = textscan(fid,...
'%f %s %f %f %f %f %f %f %s %s %f %f',...
'Headerlines', 1,...
'Delimiter',',');
fclose(fid);
% Delete 10th element ('ASC')
C(10) = [];
% Mass-convert dates to datenums
C{2} = datenum(C{2}, 'dd/mm/yyyy');
% Map 'P' to 1 and 'C' to 2
map('PC') = [1 2];
C{9} = map([C{9}{:}]).';
% Convert whole array to numeric array
C = [C{:}];
我也遇到了同样的问题…我更希望有一个2-d单元阵列,以便于访问和利用内置的matlab排序功能 下面是另一个可能适用于您的解决方案(这是TMW在导入工具中自动生成的代码中的工作方式)。它将数值数组转换为单元数组,以便您可以将它们连接成二维矩阵
C([1,3,4,5,6,7,8,11,12]) = cellfun(@(x) num2cell(x), C([1,3,4,5,6,7,8,11,12]),'UniformOutput', false);
C = [C{1:end}];
单元格数组是可以存储不同类型值的数组。这里有一个存储数字列和字符串的单元格数组。假设您所拥有的只是数值,因此单元格数组确实是冗余的,并且可以将其转换为矩阵,这更易于操作。但是,当你涉及到字符串时,你希望得到什么呢?谢谢你的回答@Rody。我理解这个问题。我正在考虑将日期和cp_标志转换为数字,并忽略ticker字段。你能告诉我这样做是否有效吗<代码>ftest=fopen('testfile2.csv');C=文本扫描(ftest、%f%s%f%f%f%f%f%f%s%s%f%f'、'Headerlines',1、'Delimiter',',');fclose(ftest);对于i=1:size(C{9})C{2}{i}=datenum(C{2}{i},'dd/mm/yyyy');如果C{9}{i}='P'C{9}{i}=1;elseif C{9}{i}='C'C{9}{i}=2;末端C{2}=cell2mat(C{2});C{9}=cell2mat(C{9});C=[C{[1 2 3 4 5 6 7 8 9 11 12]}@japa:虽然你的方法没有错,但我编辑了一个更短、更快、更复杂的版本:)非常感谢你@Rody,像这样速度非常快。它大约在10秒内处理1052480行文件。非常感谢你!
C([1,3,4,5,6,7,8,11,12]) = cellfun(@(x) num2cell(x), C([1,3,4,5,6,7,8,11,12]),'UniformOutput', false);
C = [C{1:end}];