使用MAT文件中的索引加载特定变量

时间:2011-03-17 14:55:06

标签: matlab indexing matrix selection mex

我在一台拥有大量RAM的机器上有一个框架,它生成一个MAT文件,其中包含一个非常大且特别命名的矩阵。该矩阵的计算仅执行一次并且花费大量时间。最后,它存储在磁盘上的MAT文件中。

在使用阶段,应加载此MAT文件。问题是我不需要所有数据 - 只需从该矩阵中选择某些列。

例如,我在文件crfh.mat中有一个矩阵'符号',大小为[500x250000],类型为double。我可能有兴趣只使用该矩阵中的'ids'加载矢量:

签名(:,ids)

有办法吗?我在网上搜索,似乎没有人表示需要这样的功能。我想写一个MEX函数select_mat(),如:

sign_sub = select_mat(mat_file,var_name,ids);

2 个答案:

答案 0 :(得分:3)

如果你有一个非常大的矩阵,你只想加载部分,我不会将它保存为.MAT文件。将矩阵写入其自己的二进制文件会更有效。然后,您可以使用FSEEK之类的函数跳转到文件中的各个索引点,并只读取您需要的内容。例如,让我们首先使用函数FWRITE

将较小的样本矩阵保存到二进制文件中
>> M = magic(5)  %# A sample matrix
M =
    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9

>> fid = fopen('bigmatrix.dat','w');  %# Open the file for writing
>> fwrite(fid,size(M),'uint8','l');   %# Write the matrix size (needed later) as
                                      %#   2 unsigned 8-bit (1-byte) integers
>> fwrite(fid,M,'uint8','l');         %# Write the matrix data as unsigned 8-bit
                                      %#   (1-byte) integers
>> fclose(fid);                       %# Close the file

现在,我们可以使用函数FREADFSEEK阅读第三列:

>> colIndex = 3;
>> fid = fopen('bigmatrix.dat','r');    %# Open the file for reading
>> sizeM = fread(fid,2,'uint8','l');    %# Read the first two bytes to get the
                                        %#   size of the matrix in the file
>> fseek(fid,sizeM(1)*(colIndex-1),0);  %# Seek forward by an amount of two
                                        %#   columns worth of bytes
>> colData = fread(fid,sizeM(1),'uint8','l');  %# Read column 3 data
>> fclose(fid);                         %# Close the file
>> disp(colData)                        %# Confirm that the right column was read
     1
     7
    13
    19
    25

这只是一个简单的例子。您可能希望将其他信息写入文件(即header information),例如矩阵中每个值的字节大小或数据类型。这可能看起来比仅仅将内容转储到.MAT文件更有用,但是,如果文件IO操作的效率是一个大问题,那么在这种情况下创建自己的文件格式来处理数据会更好。

答案 1 :(得分:2)

您可以从具有多个变量的.mat文件中加载特定变量。但是,我认为你不能在MATLAB中的变量中加载一组任意索引。

也就是说,如果您的问题属于您只需要访问特定行/列的类型,那么我可能会为您提供一种解决方法。

您可以从矩阵中创建struct,将每列作为单独的字段,然后使用.mat选项保存-struct文件,以便将每个字段另存为单独的字段变量。这样,你就可以拿出你想要的那个。

dummy=randn(100,200);%# this is a test matrix
[dim1,dim2]=size(dummy);

dummyCell=mat2cell(dummy,dim1,ones(dim2,1));%# create a cell from the matrix
fieldNames=strcat(repmat({'col'},1,dim2),cellfun(@num2str,mat2cell(1:dim2,1,ones(dim2,1)),'UniformOutput',false));%# generate fieldnames for the struct

dummyStruct=cell2struct(dummyCell,fieldNames,2);%# create the struct
save('myDummyFile','-struct','dummyStruct')

我不知道将矩阵直接转换为结构的方法。因此,您首先将每个列拆分为单元格(排序是因为您指示需要访问列。如果您需要行,则必须切换内容)。这是在单元格dummyCell中。现在要保存到结构,我们需要生成字段名称。这是在字符串单元格fieldNames中。它会生成col1col2等形式的字段名称...如果需要,可以将其命名为有意义的名称。然后,我们将cell转换为struct,方法是将每个单元格分配给相应的字段名称。最后,使用-struct选项保存mat文件,该选项告诉MATLAB将每个字段保存为单独的变量。当您的程序保存巨型mat文件时,所有这一切都应该完成。现在,如果您需要访问,请说col52,您需要做的就是load('myDummyFile','col52')。如果需要,您还可以加载多个。

请记住,如果您需要访问矩阵中的任意索引,如果您对索引要求(即每行/每列)有一个订单,那么这种方法很有效,那么这将无效。创建单元格/结构并保存时,可能会有一些相关的开销。但是,如果您只需要保存一次,而且经常访问,这将获得回报。

如果您的矩阵很大(按照今天的标准,500x250000并不是那么大),您必须注意这种方法的内存问题,因为我们将整个矩阵复制到一个单元格中。结构。我一步一步地编写它以便更清楚地理解,但是你可以通过从dummy创建一个单元并将其分配给自身以及类似于结构来减少重复。但是,这只会将副本数量减少1,因为Matlab仍然需要将变量复制到内存中,以便在操作后分配给它自己。