如何提高STRREAD()的速度?
How to improve the speed of STRREAD()?
我有一个名为 'datetime' 的元胞数组,格式如下:
2009.01.01 00:00:02.169
这个 'datetime' 数组是 1819833x1 大小,很大!!!
我想将它分成 2 个元胞数组:'date' 和 'time'。
日期='2009.01.01' 和时间='00:00:02.169'.
所以我使用 for 循环如下:
for i=1:numel(datetime)
[date(i), time(i)] = strread(datetime{i},'%s%s','delimiter',' ');
end
如你所见,它使用循环,处理这么大的数据时速度非常慢。
我今天下午尝试了代码,差不多一个小时过去了,工作仍然没有完成....
所以有人可以给我建议吗?
谢谢!
这是一种方法。不确定速度有多快:
datetime = {'2009.01.01 00:00:02.169'
'2009.01.02 00:01:05.169'}; %// example data. Cell array of strings
datetime_split = regexp(datetime, '\s+', 'split'); %// split according to spaces
%// Alternatively: datetime_split = cellfun(@strsplit, datetime, 'uniformoutput', 0);
datetime_split = [datetime_split{:}];
date = datetime_split(1:2:end);
time = datetime_split(2:2:end);
根据以上数据,产生
>> date
date =
'2009.01.01' '2009.01.02'
>> time
time =
'00:00:02.169' '00:01:05.169'
所以首先我会预先分配 date
和 time
,不管你选择哪个解决方案。接下来我用以下设置做了一些实验
s = '2009.01.01 00:00:02.169';
S = repmat({s}, 100000, 1);
结果是
使用strread
tic, for i=1:numel(S), [~, ~] = strread(S{i},'%s%s','delimiter',' '); end, toc
Elapsed time is 3.694143 seconds.
使用regexp
tic, for i=1:numel(S), [~] = regexp(S{i},'\s+', 'split'); end, toc
Elapsed time is 1.324754 seconds.
使用cellfun
tic, cellfun(@(x) regexp(x, '\s+', 'split'), S, 'UniformOutput', false); toc
Elapsed time is 2.072437 seconds.
如您所见,这些方法中的大多数都非常缓慢。幸运的是,MATLAB 中的很多函数都可以直接使用单元格,看这个:
tic, Sresult = regexp(S, '\s+', 'split'); toc
Elapsed time is 0.253819 seconds.
您现在可以通过 Sresult{i}{1}
或 Sresult{i}{2}
或简单地
访问结果
date = cellfun(@(x) x{1}, Sresult, 'UniformOutput', false);
time = cellfun(@(x) x{2}, Sresult, 'UniformOutput', false);
Elapsed time is 0.835277 seconds.
超快速方法
我能想到的最快的方法是要求格式始终相同,即每个字符串的长度相等。在你的情况下,我可以想象这是真的。然后你可以使用这样的东西
tic, Sa = cell2mat(S); Sdate = Sa(:,1:10); Stime = Sa(:, 12:end); toc
Elapsed time is 0.060586 seconds.
在这里你得到另一个大约 20 的速度因子!
所以,谢谢罗伯特……你的建议真的很有帮助!!!
首先,我做了预分配,循环 + strread() 组合的时间减少到 小于 40s 我的 'datetime' 数组是 1819833x1 大小。
所以这是主要的改进,我们可以看到内存重新分配和内存数据复制的减少可以大大加快这个过程....特别是当你对大量样本数据执行时。
我有一个名为 'datetime' 的元胞数组,格式如下: 2009.01.01 00:00:02.169
这个 'datetime' 数组是 1819833x1 大小,很大!!! 我想将它分成 2 个元胞数组:'date' 和 'time'。 日期='2009.01.01' 和时间='00:00:02.169'.
所以我使用 for 循环如下:
for i=1:numel(datetime)
[date(i), time(i)] = strread(datetime{i},'%s%s','delimiter',' ');
end
如你所见,它使用循环,处理这么大的数据时速度非常慢。 我今天下午尝试了代码,差不多一个小时过去了,工作仍然没有完成....
所以有人可以给我建议吗? 谢谢!
这是一种方法。不确定速度有多快:
datetime = {'2009.01.01 00:00:02.169'
'2009.01.02 00:01:05.169'}; %// example data. Cell array of strings
datetime_split = regexp(datetime, '\s+', 'split'); %// split according to spaces
%// Alternatively: datetime_split = cellfun(@strsplit, datetime, 'uniformoutput', 0);
datetime_split = [datetime_split{:}];
date = datetime_split(1:2:end);
time = datetime_split(2:2:end);
根据以上数据,产生
>> date
date =
'2009.01.01' '2009.01.02'
>> time
time =
'00:00:02.169' '00:01:05.169'
所以首先我会预先分配 date
和 time
,不管你选择哪个解决方案。接下来我用以下设置做了一些实验
s = '2009.01.01 00:00:02.169';
S = repmat({s}, 100000, 1);
结果是
使用strread
tic, for i=1:numel(S), [~, ~] = strread(S{i},'%s%s','delimiter',' '); end, toc
Elapsed time is 3.694143 seconds.
使用regexp
tic, for i=1:numel(S), [~] = regexp(S{i},'\s+', 'split'); end, toc
Elapsed time is 1.324754 seconds.
使用cellfun
tic, cellfun(@(x) regexp(x, '\s+', 'split'), S, 'UniformOutput', false); toc
Elapsed time is 2.072437 seconds.
如您所见,这些方法中的大多数都非常缓慢。幸运的是,MATLAB 中的很多函数都可以直接使用单元格,看这个:
tic, Sresult = regexp(S, '\s+', 'split'); toc
Elapsed time is 0.253819 seconds.
您现在可以通过 Sresult{i}{1}
或 Sresult{i}{2}
或简单地
date = cellfun(@(x) x{1}, Sresult, 'UniformOutput', false);
time = cellfun(@(x) x{2}, Sresult, 'UniformOutput', false);
Elapsed time is 0.835277 seconds.
超快速方法
我能想到的最快的方法是要求格式始终相同,即每个字符串的长度相等。在你的情况下,我可以想象这是真的。然后你可以使用这样的东西
tic, Sa = cell2mat(S); Sdate = Sa(:,1:10); Stime = Sa(:, 12:end); toc
Elapsed time is 0.060586 seconds.
在这里你得到另一个大约 20 的速度因子!
所以,谢谢罗伯特……你的建议真的很有帮助!!! 首先,我做了预分配,循环 + strread() 组合的时间减少到 小于 40s 我的 'datetime' 数组是 1819833x1 大小。
所以这是主要的改进,我们可以看到内存重新分配和内存数据复制的减少可以大大加快这个过程....特别是当你对大量样本数据执行时。