【问题标题】:2 columns in VAL field of accumarray - Matlabaccumarray 的 VAL 字段中的 2 列 - Matlab
【发布时间】:2011-12-20 11:47:30
【问题描述】:

我不太习惯在 Matlab 中使用 accumarray 函数,尽管我已经开始欣赏它的强大功能了!我想知道是否可以在 accumarray 函数的 VAL 字段中输入 2 个列。请看-

sz = 3  ; % num_rows for each ID
mat1 = [1 20 ; 1 40 ; 1 50 ; 2 10 ; 2 100 ; 2 110] ; % Col1 is ID, Col2 is Value
idx  = [30 1000 ; 30 1200 ; 30 1500 ; 30 1000 ; 30 1200 ; 30 1500 ] ; 
% col1: index ID, col2: value

mat1 是 ID 返回,而 idx 是索引返回。为简单起见,重复 idx 返回以匹配 mat1。 mat1 中的所有 ID 都具有相同的行。甚至 idx 也有相同的行。

[~,~,n] = unique(mat1(:,1), 'rows', 'last') ;
fncovariance = @(x,y) (x.*y)/sz ;
accumarray(n, [x(:,2) y(:,2)], [], fncovariance) % --> FAILS as VAL is not-vector!

您可以看到我正在尝试计算协方差 (cov(x,y,1)) 但不能直接使用 Matlab 的函数,因为 mat1 具有 ID,并且我需要每个 ID w.r.t 索引的协方差。

Ansmat:

    1 2444.4
    2 7888.9

【问题讨论】:

  • 最后一行代码中的xy 是什么?你的意思是mat1idx
  • @John 是的。但我只是指matlab的内置函数。对我来说,mat1 有很多 ID,y 有指数(比如纽约证券交易所)回报。所以一个简单的 cov(x,y,1) 是没有用的。谢谢。

标签: matlab matrix vectorization covariance


【解决方案1】:

简短的回答是否定的。accumarray()帮助中,关键部分是:

"VAL 必须是长度相同的数值、逻辑或字符向量 作为 SUBS 中的行数。 VAL 也可以是一个标量,其值为 对所有 SUBS 行重复。"

这意味着您甚至无法通过使用单元格来伪造它。

但是,如果你把 ID 放在自己的索引变量中,然后重新整形你的数据,使不同 ID 对应的数据在不同的列中,bsxfun() 可以有效地处理这个问题。作为参考,我还包括了一个矩阵数学方法,一个使用cov() 的简单for 循环方法,以及一个使用自定义fncovariance() 函数的cellfun() 方法(注意我在上面修改了它)。

fncovariance = @(x,y) mean(x.*y) - mean(x)*mean(y);

IDs = unique(mat1(:,1));
ret = reshape(mat1(:,2), sz, length(IDs));
idx = idx(1:sz, 2);
% bsxfun method
mean(bsxfun(@times, ret, idx)) - bsxfun(@times, mean(ret), mean(idx))
% matrix math
idx' * ret / length(idx) - mean(ret)*mean(idx)
% for loop method
id_cov = zeros(1, length(IDs));
for i=1:length(IDs)
    tmp = cov(ret(:,i), idx, 1);
    id_cov(i) = tmp(2,1);
end
id_cov
% cellfun method
ret_cell = num2cell(ret, 1);
idx_cell = num2cell(repmat(idx, 1, length(IDs)), 1);
cellfun(fncovariance, ret_cell, idx_cell)

如果你模拟更多的数据和时间这些不同的方法,bsxfun()的方式是最快的:

sz    = 10;
n_ids = 100;

IDs = 1:n_ids;
ret = randi(1000, sz, n_ids);
idx = randi(1000, sz, 1);
Elapsed time is 0.001292 seconds.
Elapsed time is 0.001523 seconds.
Elapsed time is 0.009625 seconds.
Elapsed time is 0.011454 seconds.

您可能感兴趣的最后一个选项是统计工具箱中的grpstats() 函数,它可以让您根据分组变量清除任意统计数据。

【讨论】:

    猜你喜欢
    • 2015-04-12
    • 2013-11-12
    • 2015-07-25
    • 2013-06-19
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    相关资源
    最近更新 更多