【发布时间】:2014-09-23 13:05:48
【问题描述】:
我正在尝试以其他应用程序可以理解的格式从 Matlab 导出数据...为此,我需要更改 NaN、Inf 和 -Inf 字符串(Matlab 默认为此类打印值)到//m、//inf+和//Inf-。
总的来说,我知道如何做到这一点。我在问如何(以及是否有可能)在 Matlab 中利用一个特定的东西。实际问题位于最后一段。
我尝试了两种方法(代码如下)。
- 在数据和
strrep()输出上使用sprintf()。这是以逐行方式完成的,以节省内存。这个解决方案比简单的fprintf()花费的时间几乎多出 10 倍。优点是内存开销低。 - 与选项 1. 相同,但对整个数据 进行一次转换。此解决方案速度更快,但容易受到内存不足异常的影响。这种方法的问题是我不想不必要地复制 数据。
代码:
rows = 50000 cols = 40 data = rand(rows, cols); % generate random matrix data([1 3 8]) = NaN; % insert some NaN values data([5 6 14]) = Inf; % insert some Inf values data([4 2 12]) = -Inf; % insert some -Inf values fid = fopen('data.txt', 'w'); %output file %% 0) Write data using default fprintf format = repmat('%g ', 1, cols); tic fprintf(fid, [format '\n'], data'); toc %% 1) Using strrep, writing line by line fprintf(fid, '\n'); tic for i = 1:rows fprintf(fid, '%s\n', strrep(strrep(strrep(sprintf(format, data(i, :)), 'NaN', '//m'), '-Inf', '//inf-'), 'Inf', '//inf+')); end toc %% 2) Using strrep, writing all at once fprintf(fid, '\n'); format = [format '\n']; tic fprintf(fid, '%s\n', strrep(strrep(strrep(sprintf(format, data'), 'NaN', '//m'), '-Inf', '//inf-'), 'Inf', '//inf+')); toc
输出:
经过的时间是 1.651089 秒。 % 正则 fprintf()
经过的时间是 11.529552 秒。 % 选项 1
经过的时间是 2.305582 秒。 % 选项 2
现在问题...
与简单的 fprintf() 相比,我对使用我的解决方案的内存开销和时间损失感到不满意。
我的理由是'NaN'、'Inf' 和'-Inf' 字符串是保存在*printf() 或*2str() 实现中的某个变量中的简单数据。有没有办法在运行时改变它们的值?
例如,在 C# 中,我将更改 System.Globalization.CultureInfo.NumberFormat.NaNSymbol 等,如 here 所述。
【问题讨论】:
-
为什么不在 MATLAB 工作区中的数据替换这些值,然后导出结果?这应该比导出时替换要快得多。
-
@EliDuenisch 因为工作区中的数据保存为 double。它必须是 string 才能让我先验地应用转换。
-
找到 NaN 等的索引,然后使用 num2cell 将数据转换为元胞数组,将索引替换为字符串,然后导出
-
@EliDuenisch 我也尝试过(以及其他几种方法),也许你可以检查我的问题的编辑历史,我没有写下我为了篇幅而尝试的所有内容。 .. 将 data 转换为元胞数组是 1) 慢(示例中为 70 秒)2) 内存很重...我不想复制所有数据,因为我们可能会说话千兆字节。
-
内部字符串转换似乎回到了一个未记录的内置辅助函数
sprintfc,据我所知,它是不可更改的。关于我建议尝试的唯一事情是使用~isfinite预先检查包含这些值之一的行数,然后在可能的情况下一次循环fprintf行块而不是遍历每一行(但是tbh 我可能会在这一点上放弃,将数据转储到文件并在事后使用非 MATLAB 方法来操作文本文件)。