我有一个非常大的大约1100万行的Matlab表,我想重新排列,为每个变量的每个实例都有一个单元格数组。以下较小的数据集将说明我的问题:
Data = table(repmat(randperm(50).',200,1),rand(10000,1),'VariableNames',{'ID','VAR'});
我能够通过以下命令执行任务,但是当应用于我的真实表时它很慢:
UniID = unique(Data.ID);
CellData = arrayfun(@(x)Data(Data.ID==x,:),UniID,'UniformOutput',false);
如何优化执行时间?
答案 0 :(得分:3)
在此之后您可能想要进行一些处理,请考虑使用:
B = varfun(@(x) {x}, Data, 'GroupingVariables', 'ID');
如果您将mean
更改为@(x) {x}
,您可以使用此功能将值分组为如上所示的组,或直接应用某些功能,如@mean
。这应该是最清晰的解决方案,但它不会给你任何速度提升。
但是,如果不使用表格,可能会获得一点速度增益,但只需使用数组。而不是'GroupingVariables'
,您可以使用accumarray
。
如果您的Data.ID
已经是正整数,则不需要任何预处理步骤(如果它们不使用:[~,~,newID] = unique(ID)
)并且可以使用:
accumarray(Data.ID, Data.VAR, [], @(x) {x})
如果您的表只有两个变量,这就足够了。如果您要处理多个变量,则必须使用类似的东西:
accumarray(Data.ID, 1:size(Data,1) ,[], @(I) {Data(I,:)})
这两者都可能改变每个细胞条目的内部排序。如果您不想这样做,请使用accumarray
的{{3}}。
由于表数据结构有一些开销,如果你不使用Data
表来访问值,这可能会更快,但数组本身:
VAR1 = rand(100000,1);
VAR2 = rand(100000,1);
ID = repmat(randperm(50).',2000,1);
VARsPartitioned = accumarray(ID, 1:numel(ID) ,[], @(I) {[VAR1(I,:), VAR2(I,:)]});
对于一百万行和5000个不同的ID,我得到了这些结果:
arrayfun: ~30 seconds
varfun: ~30 seconds
accumarray using table: ~3 seconds
accumarray using arrays: ~0.3 seconds
PS:您还可以使用@mean
或@std
直接使用accumarray
,而无需在第一步中对变量进行分组。