匹配 ID +在Matlab中查找矩阵中的数字

发布于 2024-11-25 16:53:31 字数 1237 浏览 0 评论 0原文

我在匹配两个矩阵中的元素时遇到问题。第一个元素可以使用 ismember 进行匹配,但第二个元素应该在一个范围内。请参见下面的示例:

% col1 is integerID, col2 is a number.       -->col1 is Countrycode, col2 is date
bigmat = [ 600 2  
           600 4  
           800 1  
           800 5  
           900 1] ;

% col1 is integerID, col2 is VALUE, col2 is a range    -->value is Exchange rate
datamat = {...
           50   0.1   [2 3 4 5 6]       % 2:6
           50   0.2   [9 10 11]         % 9:11
           600  0.01  [1 2 3 4]         % 1:4
           600  0.2   [8 9 10]          % 8:10
           800  0.12  [1]               % 1:1
           800  0.13  [3 4]             % 3:4
           900  0.15  [1 2]      } ;    % 1:2

I need the answer as:
    ansmat = [ 600 2  0.01
               600 4  0.01
               800 1  0.12
               800 5  nan               % even deleting this row is fine
               930 1  0.15 ] ;

为简单起见:

  1. matrix_1 中的所有 intID 都存在于matrix_2 中。
  2. 范围内的数字是日期!在某个范围内,这些数字是连续的: [1 2...5]
  3. 对于任何 ID,下一行中的日期不连续。例如,您可以在下一行看到 [1 2 3 4],然后看到 [8 9 10]。

bigmat是一个巨大的矩阵! 300,000-500,000 行,因此矢量化代码将受到赞赏。 datamat 大约为 5000 行或更少。您可以将单元格转换为矩阵。对于每一行,我都有最小值和最大值。第 3 列是最小值:最大值。谢谢!

I am facing a problem in matching elements in 2 matrices. The first element can be matched using ismember but the second element should be within a range. Please see the example below:

% col1 is integerID, col2 is a number.       -->col1 is Countrycode, col2 is date
bigmat = [ 600 2  
           600 4  
           800 1  
           800 5  
           900 1] ;

% col1 is integerID, col2 is VALUE, col2 is a range    -->value is Exchange rate
datamat = {...
           50   0.1   [2 3 4 5 6]       % 2:6
           50   0.2   [9 10 11]         % 9:11
           600  0.01  [1 2 3 4]         % 1:4
           600  0.2   [8 9 10]          % 8:10
           800  0.12  [1]               % 1:1
           800  0.13  [3 4]             % 3:4
           900  0.15  [1 2]      } ;    % 1:2

I need the answer as:
    ansmat = [ 600 2  0.01
               600 4  0.01
               800 1  0.12
               800 5  nan               % even deleting this row is fine
               930 1  0.15 ] ;

For simplicity:

  1. All intIDs from matrix_1 exist in matrix_2.
  2. The numbers in range are dates! Within a range, these numbers are consecutive: [1 2...5]
  3. For any ID, dates in the next row are not continuous. Eg, you can see [1 2 3 4] and then [8 9 10] in next row.

bigmat is a huge matrix! 300,000-500,000 rows and so a vectorized code would be appreciated. datamat is roughly 5000 rows or less. You can convert the cell to matrix. For each row, I have the minimum and maximum. The 3 column is minimum:maximum. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迎风吟唱 2024-12-02 16:53:31

这是一种可能的实现:

%# data matrices
q = [
    600 2  
    600 4  
    800 1  
    800 5  
    900 1
];
M = {
    50   0.1   [2 3 4 5 6]
    50   0.2   [9 10 11]
    600  0.01  [1 2 3 4]
    600  0.2   [8 9 10]
    800  0.12  [1]
    800  0.13  [3 4]
    900  0.15  [1 2]
};

%# build matrix: ID,value,minDate,maxDate
M = [cell2num(M(:,1:2)) cellfun(@min,M(:,3)) cellfun(@max,M(:,3))];

%# preallocate result
R = zeros(size(M,1),3);

%# find matching rows
c = 1;             %# counter
for i=1:size(q,1)
    %# rows indices matching ID
    ind = find( ismember(M(:,1),q(i,:)) );

    %# out of those, keep only those where date number is in range
    ind = ind( M(ind,3) <= q(i,2) & q(i,2) <= M(ind,4) );

    %# check if any
    num = numel(ind);
    if num==0, continue, end

    %# extract matching rows
    R(c:c+num-1,:) = [M(ind,1) repmat(q(i,2),[num 1]) M(ind,2)];
    c = c + num;
end

%# remove excess
R(c:end,:) = [];

预期结果:

>> R
R =
          600            2         0.01
          600            4         0.01
          800            1         0.12
          900            1         0.15

Here is one possible implementation:

%# data matrices
q = [
    600 2  
    600 4  
    800 1  
    800 5  
    900 1
];
M = {
    50   0.1   [2 3 4 5 6]
    50   0.2   [9 10 11]
    600  0.01  [1 2 3 4]
    600  0.2   [8 9 10]
    800  0.12  [1]
    800  0.13  [3 4]
    900  0.15  [1 2]
};

%# build matrix: ID,value,minDate,maxDate
M = [cell2num(M(:,1:2)) cellfun(@min,M(:,3)) cellfun(@max,M(:,3))];

%# preallocate result
R = zeros(size(M,1),3);

%# find matching rows
c = 1;             %# counter
for i=1:size(q,1)
    %# rows indices matching ID
    ind = find( ismember(M(:,1),q(i,:)) );

    %# out of those, keep only those where date number is in range
    ind = ind( M(ind,3) <= q(i,2) & q(i,2) <= M(ind,4) );

    %# check if any
    num = numel(ind);
    if num==0, continue, end

    %# extract matching rows
    R(c:c+num-1,:) = [M(ind,1) repmat(q(i,2),[num 1]) M(ind,2)];
    c = c + num;
end

%# remove excess
R(c:end,:) = [];

The result as expected:

>> R
R =
          600            2         0.01
          600            4         0.01
          800            1         0.12
          900            1         0.15
唔猫 2024-12-02 16:53:31

我不完全确定我理解..第二个条目应该是“600 4 0.02”吗?

无论如何,您可以尝试类似的操作:

% grab first column
col = bigmat(:, 1);

% find all entries in column that are equal to ID
rel = (col == id);

% retrieve just those rows
rows = bigmat(rel, :);

然后,一旦您从矩阵中获得了所需的行,您就可以将它们连接在一起,如下所示:

result = [rowsA(1:3) rowsB(2) rowsC(5:6)];

I'm not completely sure I understand .. should the second entry be '600 4 0.02'?

Anyways, you may be able to try something like:

% grab first column
col = bigmat(:, 1);

% find all entries in column that are equal to ID
rel = (col == id);

% retrieve just those rows
rows = bigmat(rel, :);

Then once you have the rows you need from your matrices, you can concatenate them together like so:

result = [rowsA(1:3) rowsB(2) rowsC(5:6)];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文