【问题标题】:Datenum function is slow. What can I do?Datenum 函数很慢。我能做些什么?
【发布时间】:2015-07-31 13:00:54
【问题描述】:

我正在尝试将字符向量(200,000 行)转换为 Matlab 序列号。
格式为'01/07/2015 00:00:59'

这需要非常长的时间,网上我只能在 Matlab 中找到解决这个问题的技巧。有什么想法可以改进吗?

【问题讨论】:

  • 您的输入可能是一个字符串元胞数组?怎么调用datenum,传格式吗?
  • 有哪些Matlab小技巧可以在线解决?你确定他们不只是在 Octave 中工作吗?
  • 使用 matlab 中的 .mex 文件的提示,这些文件在 octave 中不可用。我的输入是一个字符串数组,但我将它转换为一个字符矩阵。这有什么不同吗?
  • @BallzofFury 提示要查看 datenum 的代码并提取为您的特定字符串格式调用的位,然后使用该代码。在 Matlab 中,它调用了一个 mex 函数,但无论 Octave 调用什么都应该更快。可以给datenum加断点吗?这个想法是跳过所有处理 datenum 确实试图弄清楚如何转换为您的特定格式
  • 我决定编写自己的脚本,因为我确实有一个标准的日期格式。效果更好,谢谢!

标签: matlab octave


【解决方案1】:

您可以对datenum 使用datenum(datevector) 类型的输入。

它比字符串解析要快得多。每当我必须导入长日期/时间数据(几乎每天)时,我经常使用这个技巧。

它包括发送一个mx6(或mx3)矩阵,其中包含代表[yy mm dd HH MM SS]的值。矩阵的类型应为double

这意味着不是让 Matlab/Octave 进行解析,而是用自己喜欢的方式(textscanfscanfsscanf、...)读取字符串中的所有数字,然后将数字发送到datenum 而不是字符串。

在下面的示例中,我生成了一个包含日期字符串的长数组 (86401x19) 作为示例数据:

>> strDate(1:5,:)
ans =
31/07/2015 15:10:13
31/07/2015 15:10:14
31/07/2015 15:10:15
31/07/2015 15:10:16
31/07/2015 15:10:17

为了比传统方式更快地将其转换为 datenum,我使用:

strDate = [strDate repmat(' ',size(strDate,1),1)] ; %// add a whitespace at the end of each line
M = textscan( strDate.' , '%f/%f/%f %f:%f:%f'  ) ;  %'// read each value independently
M = cell2mat(M) ;                                   %// convert to matrix
M = M(:,[3 2 1 4 5 6]) ;                            %// reorder columns

dt = datenum(M ) ;                                  %// convert to serial date

这应该会提高 Matlab 中的速度,但我很确定它也会改进 Octave 中的内容。为了至少在 Matlab 上量化这一点,这里有一个快速基准:

function test_datenum

d0 = now ;
d = (d0:1/3600/24:d0+1).' ; %// 1 day worth of date (one per second)

strDate = datestr(d,'dd/mm/yyyy HH:MM:SS') ; %'// generate the string array

fprintf('Time with automatic date parsing: %f\n' , timeit(@(x) datenum_auto(strDate)) )
fprintf('Time with customized date parsing: %f\n', timeit(@(x) datenum_preparsed(strDate)) )


function dt = datenum_auto(strDate)
    dt = datenum(strDate,'dd/mm/yyyy HH:MM:SS') ;       %// let Matlab/Octave do the parsing


function dt = datenum_preparsed(strDate)
    strDate = [strDate repmat(' ',size(strDate,1),1)] ; %// add a whitespace at the end of each line
    M = textscan( strDate.' , '%f/%f/%f %f:%f:%f'  ) ;  %'// read each value independently
    M = cell2mat(M) ;                                   %// convert to matrix

    M = M(:,[3 2 1 4 5 6]) ;                            %// reorder columns

    dt = datenum(M ) ;                                  %// convert to serial date

在我的机器上,它产生:

>> test_datenum
Time with automatic date parsing: 0.614698
Time with customized date parsing: 0.073633

当然你也可以用几行压缩代码:

M = cell2mat(textscan([strDate repmat(' ',size(strDate,1),1)].','%f/%f/%f %f:%f:%f'))) ;
dt = datenum( M(:,[3 2 1 4 5 6]) ) ;

但我对其进行了测试,但改进是如此微不足道,以至于失去可读性并不值得。

【讨论】:

    猜你喜欢
    • 2015-10-23
    • 2014-09-06
    • 1970-01-01
    • 2019-01-23
    • 2013-04-19
    • 2011-10-25
    • 2014-03-18
    • 2012-06-01
    • 2013-10-10
    相关资源
    最近更新 更多