我有一个ID号重复偶数次的矢量。我只对每个数字出现的第二次感兴趣。我想创建一个布尔掩码,为每个第二次出现的数字提供一个真/ 1。我已经用循环完成了这个,但实际的向量将包含数百万个元素,因此循环太慢了。我需要一个“矢量化”解决方案。
这是一个示例Vector:
101
102
103
101
104
102
101
103
101
104
这应该输出以下掩码:
0 (first occurrence of 101)
0 (first occurrence of 102)
0 (first occurrence of 103)
1 (second occurrence of 101)
0 (first occurrence of 104)
1 (second occurrence of 102)
0 (third occurrence of 101)
1 (second occurrence of 103)
1 (fourth occurrence of 101)
1 (second occurrence of 104)
答案 0 :(得分:4)
您可以通过unique
和accumarray
的组合轻松完成此操作。首先为每个值分配一个唯一的ID,然后将所有阵列位置合并在一起,这些位置是同一ID的一部分。您需要对它们进行排序,因为accumarray
不能保证在您将所有内容组合在一起时的订单。这个输出将是一个单元格数组,其中每个单元格为您提供特定索引所发生的数组位置。
执行此操作后,从accumarray
生成的每个单元格中提取出每个第二个元素,然后使用这些元素将掩码中的所有相应位置设置为1.您可以使用{{3}的组合},可用于单独处理每个单元格并提取每个第二个元素以创建新的单元格数组,以及cellfun
可用于将所有单元格数组合在一起形成一个最终索引数组。此索引数组可用于完成将掩码中的位置设置为true
:
%// Your data
V = [101,102,103,101,104,102,101,103,101,104];
%// Get list of unique IDs
[~,~,id] = unique(V,'stable');
%// Bin all of the locations in V together that belong to the
%// same bin
out = accumarray(id, (1:numel(V)).',[], @(x) {sort(x)}); %'
%// Extract out every second value that is for each bin
out2 = cellfun(@(x) x(2:2:end), out, 'uni', 0);
%// Create a mask and set the corresponding locations to true
mask = false(numel(V), 1);
mask(vertcat(out2{:})) = 1;
我们得到:
>> mask
mask =
0
0
0
1
0
1
0
1
1
1
答案 1 :(得分:3)
这是一种方法:
A = [101,102,103,101,104,102,101,103,101,104];
IDs = unique(A); % Find all the IDs present
test = arrayfun(@(x) find(A==x), IDs, 'UniformOutput', false); % Per ID, find where A == ID
repeatidx = cellfun(@(x) x(2:2:length(x)), test, 'UniformOutput', false); % Dump out the second match
repeatidx = cell2mat(repeatidx); % Flatten the cell array
B = false(size(A)); % Intialize output boolean array
B(repeatidx) = true; % Set true values based on repeatidx
返回:
B =
0 0 0 1 0 1 0 1 1 1
答案 2 :(得分:3)
让它bsxfun
用于矢量化解决方案 -
%// Assuming A as the input vector
M = bsxfun(@eq,A(:),unique(A(:).')) %//'
out = any(M - mod(cumsum(M,1).*M,2),2)