2011-10-28 10 views
1

IDごとに複数の行を持つ行列があります。私は言葉だけを抽出する必要があります.4 IDごとに最後の行。 IDのCOLSは2 Colsはからなる:行列内の各IDに対して "n"行を抽出する - MATLAB

mat = [ ... 
     2222 1 734771 0.11 
     2222 1 734772 0.22 
     2222 1 734773 0.33 
     2222 1 734774 0.44 
     2222 1 734775 0.55 
     5555 3 734771 0.11 
     5555 1 734772 0.12 
     5555 1 734773 0.13 
     ] ; 

答え - > %[2222 1 734772 0.22。 2222 1 734773 0.33; 2222 1 734774 0.44; 2222 1 734775 0.55]

ベクトル化されたアプローチを理解できます。ありがとう、幸せなハロウィン!

答えて

2

ここではUNIQUEおよびを使用して効率的なソリューションです。の機能:独自機能の第三の出力を用いて

%# sample matrix, sorted by first column 
mat = [randi([1 5],[20 1]) (1:20)' rand(20,1)]; %' 
mat = sortrows(mat); 

%# extract last N rows from each unique ID 
N = 4; 
[~,~,subs] = unique(mat(:,1));     %# index into unique values 
fcn = @(x){ x(max(1,end-N+1):end) };    %# at most last N values 
ind = accumarray(subs, 1:numel(subs), [max(subs) 1], fcn); 
ind = cell2mat(ind(cellfun(@numel,ind) >= 4)); %# keep only those with 4+ count 
result = mat(ind,:) 

は、我々は、行ごとに一意のIDのリストへのインデックスを取得します。次に、それらの添え字に基づいて行インデックスをビン(セル配列)に配布します。各ビンから最後の4つのインデックスを取り出し、4回未満のものをフィルタリングします。次にそれらをすべて1つの行インデックスのベクトルに結合します。最後に元の行列から対応する行を取得するために使用します。上記の例を使用して

、我々は次の行列を生成:

mat = 
      1   2  0.70199 
      1   6  0.46313 
      1   7  0.98821 
      1   12  0.15645 
      1   13  0.67037 
      1   16  0.86966 
      2   8  0.63491 
      2   9  0.076501 
      2   15  0.55076 
      2   17  0.44727 
      2   19  0.30587 
      3   5  0.91502 
      3   10  0.97322 
      3   20  0.48231 
      4   3  0.45633 
      4   4  0.12363 
      4   11  0.18319 
      4   14  0.36045 
      5   1  0.36708 
      5   18  0.63084 

をし、その結果は以下のとおりであった:

result = 
      1   7  0.98821 
      1   12  0.15645 
      1   13  0.67037 
      1   16  0.86966 
      2   9  0.076501 
      2   15  0.55076 
      2   17  0.44727 
      2   19  0.30587 
      4   3  0.45633 
      4   4  0.12363 
      4   11  0.18319 
      4   14  0.36045 
+0

ありがとうAmro。何らかの理由で、上記の例でコードが正しく動作しません。私は1つではなく2つのcolを使用するように独自のfncを修正しましたが、まだ5555を集めています(カウントは<4行であるので削除する必要があります)。感謝しなければならない。 – Maddy

+0

@Maddy:あなたの最初の記述から、4つ以下の固有のIDの出現で行を保持したいかどうかはっきりしていませんでした。とにかく、最近の修正を参照してください – Amro

+0

ありがとう!私はより完全に理解する必要があります。私はreshape()などを使用して新しいアプローチを設計しましたが、あなたのソリューションははるかに短くエレガントです。 – Maddy

0

ないあなたが見た中で最も効率的な実装が、それは動作します:

明らか
a = [1 1 1 1 2 2 2 2 3 3 ]; 
b = unique(a); 

for i = 1:length(b) 
    c = b(i); 
    ind = find(a==c); 
    last4 = ind(end-1:end) %adjust how many elements you want 
end 

、あなたが行列を持っている場合は、物事はあなたが

0
X=[]; 
id=ones(size(mat,1),1)==1; 
for n=1:4 
    [~, m, ~]=unique(mat(id,1:2),'rows'); 
    X=[X; mat(m,:)]; 
    id(m)=0; 
end 
return X 
を心配している場合、列のインデックスを追加する必要があると思います

(あなたの例では、あなたが5555行のいずれかを返しませんでしたが、私はあなたがそれらをしたいと仮定答える。)

+0

こんにちはサイボーグ、返信に感謝を。私は '5555'を除外しました。なぜなら、この例では<4行が必要だったからです! – Maddy

関連する問題