2

有没有一种聪明的方法从成对的二维数组中获取值以及行中的最后一个数字?

我的数据(保存在文件中)类似于以下内容:

  0  89  27 100  42  75 8  
  0 100   7  92   5  68 6  
  0  67  49  83 100 100 2  
 35  76  57 100 100  92 5  
 18  68  50  54 100  19 3  

将此数据加载到 Matlab 后,我需要通过始终采用 Pairs 将数据分组到元组中。在此示例中,它将是:

[0,89],[27,100],[42,75],[0,100],...[100,19]

在配对数据(或同时)之后,我需要将行中的最后一个数字添加到对中。前面提到的数据将进行如下更改:

[0,89,8],[27,100,8],[42,75,8],[0,100,6],...[100,19,3]

如何解决这个问题?我个人不喜欢 Loops 的广泛使用,并认为有更好的解决方案。

4

5 回答 5

2

我认为没有人想出这个真是太神奇了:

M = [   
  0  89  27 100  42  75 8  
  0 100   7  92   5  68 6  
  0  67  49  83 100 100 2  
 35  76  57 100 100  92 5  
 18  68  50  54 100  19 3  ];


C = arrayfun(...
    @(ii) [M(:,ii:ii+1) M(:,end)], ...
    1:2:size(M,2)-1, 'UniformOuput', false);

你最终会得到这个单元格数组:

>> C{1}

ans =

     0    89     8
     0   100     6
     0    67     2
    35    76     5
    18    68     3

>> C{2}

ans =

    27   100     8
     7    92     6
    49    83     2
    57   100     5
    50    54     3

>> C{3}

ans =

    42    75     8
     5    68     6
   100   100     2
   100    92     5
   100    19     3

现在您可以像这样引用单个元组:

C{1}(2,:)   %  [  0   100   6]
C{3}(4,:)   %  [100    92   5]
于 2012-10-31T19:56:20.517 回答
2

编辑:这应该可以解决问题。

M=[0  89  27 100  42  75 8  
  0 100   7  92   5  68 6  
  0  67  49  83 100 100 2  
 35  76  57 100 100  92 5  
 18  68  50  54 100  19 3]

X = M(:,1:end-1)
Y = M(:,end)
idxOdd = mod(1:size(X,2),2)==1
Xeven=X(:,~idxOdd)
Xodd=X(:,idxOdd)

Yrep = repmat(Y,1,sum(idxOdd))

[Xodd(:) Xeven(:) Yrep(:)]
于 2012-10-31T16:50:15.963 回答
1

为了对矩阵中的数据进行分组A,您可以使用cell2mat并输出一个单元格元组数组C,然后在该数组的相应行中附加最后一列元素:

% separate the data pairs
C = mat2cell(A(:,1:end-1), ones(1,size(A,1)), 2*ones(1,3));

% single for-loop to append line_lat_element in cells of same row
for i = 1:size(A,1)
    D(i,:) = cellfun(@(x) [x A(i,end)], {C{i,:}}, 'UniformOutput', false);
end

作为输出,D{i,j}元胞数组的每个条目都将包含三元组[data1 data2 last_element_of_line]

于 2012-10-31T17:28:16.567 回答
1

在这种情况下,我想为卑微的for循环辩护:

M = [  0  89  27 100  42  75 8  ;
         0 100   7  92   5  68 6  ;
         0  67  49  83 100 100 2  ;
        35  76  57 100 100  92 5  ;
        18  68  50  54 100  19 3 ];

out = zeros((size(M,2)-1)/2*size(M,1),3);
ind = 1;
for row = 1:size(M,1)
    for col = 1:2:(size(M,2)-1)
        out(ind,:) = [M(row,col:col+1) M(row,end)];
        ind = ind+1;
    end
end
out

我声称这比非循环版本更容易编写、理解和维护(无论是对于刚接触代码的程序员,还是同一个程序员在数周、数月或数年后返回代码)。唯一有点棘手的部分是计算输出矩阵的正确大小out。如果性能成为问题,那么当然,请查看非循环版本。但是最近版本的 MATLAB 运行 for 循环的速度比过去快得多,那么为什么要过早优化呢?

您可以通过基于rowand的巧妙计算来消除保持运行索引的需要col,但为什么要麻烦呢?上面的代码很简单,程序员很容易理解

于 2012-10-31T17:38:06.463 回答
1

这可以使用逻辑索引来完成。以丹尼斯的回答为基础:

z = M(:,end); %# extract the last column
M = M(:,1:end-1); %# chop off the last column from the rest of your data
xidx = logical(mod(1:size(M,2),2)); %# get a logical index of the odd numbered rows
x = M(:,xidx); %# grab the x values
y = M(:,~xidx); %# grab the y values
z = repmat(z,1,numel(x)/numel(z)); % replicate z to match numel of x and y
x = reshape(x',numel(x),1);    %# reshape the arrays to form the right dimensions
y = reshape(y',numel(y),1);
z = reshape(z',numel(z),1);
output = [x,y,z]; %# format output
于 2012-10-31T17:16:37.360 回答