无循环变换矩阵

时间:2017-01-09 16:09:11

标签: matlab for-loop

我有oldMat这是股票代码的排名。列号表示相应的等级,例如第一列等于最高等级,第二列等于第二高等级,依此类推。 oldMat中的整数表示个人股票代码的数量。 3中的数字oldMat(3,2,1)表示第三个股票代码在第三个时期排名第二(行代表不同的时期)。

现在,我需要通过以下方式转换oldMat:列号现在代表各个股票代码。整数现在代表个别股票代码在特定时期持有的等级。例如,2中的数字newMat(3,3,1)表示第三个股票代码在第三个时期排名第二。

我使用for循环来解决这个问题,但我很确定存在一种更有效的方法来实现这个结果。这是我的代码:

% Define oldMat
oldMat(:,:,1) = ...
    [NaN, NaN, NaN, NaN, NaN, NaN; ...
    1, 3, 4, 6, 2, 5; ...
    6, 3, 4, 1, 2, 5; ...
    2, 3, 6, 1, 4, 5; ...
    5, 4, 6, 2, 3, 1; ...
    5, 1, 2, 3, 6, 4; ...
    4, 5, 1, 3, 6, 2; ...
    4, 1, 6, 5, 2, 3];
oldMat(:,:,2) = ...
    [NaN, NaN, NaN, NaN, NaN, NaN; ...
    NaN, NaN, NaN, NaN, NaN, NaN; ...
    1, 6, 3, 4, 2, 5; ...
    6, 3, 2, 1, 4, 5; ...
    2, 6, 3, 4, 1, 5; ...
    5, 2, 1, 6, 3, 4; ...
    5, 1, 3, 6, 2, 4; ...
    4, 1, 5, 6, 3, 2];

% Pre-allocate newMat
newMat = nan(size(oldMat));

% Transform oldMat to newMat
for runNum = 1 : size(newMat,3)

    for colNum = 1 : size(newMat,2)

        for rowNum = 1 : size(newMat,1)
            if ~isnan(oldMat(rowNum, colNum, runNum))
                newMat(rowNum,oldMat(rowNum, colNum, runNum), runNum) = colNum;
            end
        end

    end

end

1 个答案:

答案 0 :(得分:2)

看起来像sub2ind的经典案例。您想要创建一组线性索引来访问新矩阵的第二个维度,并将其设置为等于列号。首先使用meshgrid创建一个3D坐标网格,然后使用oldMat矩阵作为输出第二列的索引,并将其设置为等于列编号。确保您不会复制任何NaN个值,否则sub2ind会抱怨。您可以使用isnan来帮助过滤这些值:

% Initialize new matrix
newMat = nan(size(oldMat));

% Generate a grid of coordinates
[X,Y,Z] = meshgrid(1:size(newMat,2), 1:size(newMat,1), 1:size(newMat,3));

% Find elements that are NaN and remove
mask = isnan(oldMat);
X(mask) = []; Y(mask) = []; Z(mask) = [];

% Set the values now
newMat(sub2ind(size(oldMat), Y, oldMat(~isnan(oldMat)).', Z)) = X;