【问题标题】:How to improve the speed of STRREAD()?如何提高 STRREAD() 的速度?
【发布时间】:2015-12-20 17:53:52
【问题描述】:

我有一个名为“datetime”的元胞数组,格式如下: 2009.01.01 00:00:02.169

这个“日期时间”数组大小为 1819833x1,很大!!! 我想将其拆分为 2 个单元格数组:“日期”和“时间”。 日期='2009.01.01' 和时间='00:00:02.169'。

所以我使用for循环如下:

for i=1:numel(datetime)
    [date(i), time(i)] = strread(datetime{i},'%s%s','delimiter',' ');
end

如您所见,它使用循环,处理如此大的数据时速度确实很慢。 我今天下午尝试了代码,差不多一个小时过去了,工作仍然没有完成....

那么有人可以给我一个建议吗? 谢谢!

【问题讨论】:

  • 有没有办法避免使用for循环?
  • 另外我的目标是最终将“日期时间”单元格数组转换为日期序列号。那么是否有更好的方法来做到这一点?
  • 对不起,我忘记了……是Matlab

标签: string performance matlab for-loop cell-array


【解决方案1】:

所以,谢谢罗伯特……你的建议真的很有帮助!!! 首先,我进行了预分配,循环 + strread() 组合的时间减少到 小于 40 秒,我的 'datetime' 数组大小为 1819833x1。

所以这是主要的改进,我们可以看到内存重新分配和内存数据复制的减少可以大大加快进程....特别是当您执行大量样本数据时。

【讨论】:

    【解决方案2】:

    所以首先我会预先分配datetime,不管你选择哪种解决方案。接下来我用以下设置做了一些实验

    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 的速度因子!

    【讨论】:

      【解决方案3】:

      这是一种方法。不知道它会有多快:

      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'
      

      【讨论】:

        猜你喜欢
        • 2018-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-02
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多