2017-01-09 118 views
1

我有oldMat这是一个股票行情的排名。列号表示各自的等级,例如,第一列等于最高等级,第二列等于第二最高等级等等。 oldMat中的整数代表个人股票报价的数量。 oldMat(3,2,1)中的3这个数字表示第三个股票代码在第三个时间段排名第二(行代表不同的时间段)。无循环变换矩阵

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

为了解决这个问题,我使用了一个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 

回答

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;