Get vector indices before-and-after (window +/- 1) given indices

淺唱寂寞╮ 提交于 2019-12-24 20:58:51

问题


What's the best Matlab/Octave idiom, given idx a vector of indices, to get the sorted vector of idx +/-1 ?

I have an n x 7 data matrix, column 3 is an integer label, and I'm interested in viewing the neighborhood of discontinuities on it. Hence I get the corresponding indices:

idx = find(diff(data(:,3)) > 0)

5297
6275
6832
...
20187

Then if I want to view that neighborhood +/- 1 on my column (e.g. on the (mx2) matrix [idx-1; idx+1]), I need to form the vector of idx-1, idx+1 either concatenated in-order, or resorted. I found some clunky ways of doing this, what's the proper way? (I tried all of the octave chapter on Rearranging Matrices)

% WAY 1: this works, but is ugly - a needless O(n) sort
sort([idx-1; idx+1])

% horzcat,vertcat,vec only stack it vertically
horzcat([idx-1; idx+1])
horzcat([idx-1; idx+1]')

% WAY 2?
%One of vec([idx-1; idx+1]) or vec([idx-1; idx+1]') should work? but doesn't, they always stack columnwise
horzcat([idx-1; idx+1]')

ans =
Columns 1 through ...
5297    6275    6832 ...  20187    5299    6277    6834 ... 20189

% TRY 3...
reshape([idx-1; idx+1], [36,1]) doesn't work either

You would expect there are only two ways to unstack a 2xm matrix, but ...


回答1:


You can do this with implicit singleton expansion (R2016b or newer MATLAB, native to Octave)

idx = [2, 6, 9]; % some vector of integers
% Use reshape with [] to tell MATLAB "however many rows it takes"
neighbours = reshape( idx + [-1;1], [], 1 );

>> neighbours = [1; 3; 6; 8; 8; 10];

If you don't know whether idx is a row or column, you can be more robust by using

neighbours = reshape( idx(:)' + [-1,1], [], 1)

If you don't want to use implicit expansion (and again coping with either row or column idx), you can use reshape like so

neighbours = reshape( [idx(:)-1, idx(:)+1]', [], 1 )

Note: you may also want to wrap the whole thing in a call to unique. In my example, you get the index 8 twice, I'm not sure if this is desirable or not in your situation.

However, unique performs a sort (unless you use the 'stable' flag but that can make it even slower), so you might as well use your original approach if you want to remove duplicates:

% Remove duplicates and sort the result using unique 
neighbours = unique( [idx-1, idx+1] );



回答2:


Hmm, I finally found this octave matrix manipulation:

vec([idx-1, idx+1]')
ans =

5297
5299
6275
6277
6832
6834
...
20187
20189

Adapting Wolfie's solution into the shortest Octave-only code:

[idx-1, idx+1]' (:)  
( idx(:)' + [-1; 1] )(:) 

idx = ( find(diff(data(:,3)) > 0 )' + [-1; 1] )(:) works as a one-liner

... and [idx , data(idx,3)] displays the indices and data, side-by-side



来源:https://stackoverflow.com/questions/48881754/get-vector-indices-before-and-after-window-1-given-indices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!