我在matlab中有一个单元数组和一个数值数组,它们本身是链接的。数字数组(A)包含来自若干数据源的一系列时间,例如每次测量的时间。该阵列是n个测量(行)的n个传感器(列)。默认情况下,数组填充-1,因为0是有效时间。
A = [ [ 100 110 -1 -1 ] ; ...
[ -1 200 180 -1 ] ; ...
[ -1 200 210 240 ] ; ...
[ 400 -1 -1 450 ] ];
对于数值数组的每一行,单元格按时间顺序包含传感器。每个单元格元素都包含一个向量,按照它们进行测量的顺序显示传感器。
C = { [1 2] [3 2] [2 3 4] [1 4]};
我希望看到相对于每个传感器的时间分布,例如传感器2/3/4(当它们存在时)相对于传感器的时间分布是多少?
例如......
传感器1参与第一次和第四次测量,其他检测器为+10(100→110)和+50(400→450)。在这种情况下,我希望返回一个数组,如[10 50]。
传感器2涉及前三个事件,其中一个是三方事件。在这种情况下,sensor2并不总是第一个触发,因此某些值将为负值。在这种情况下,我希望返回[-10 -20 +10 +40)]
使用相同的逻辑传感器3应返回[20 -10 30]和sensor4 [-40 -30 -50]。
我确信应该有一个简单的方法来做到这一点,但我无法理解它。当然我给出的例子是一个非常简单的例子....通常我正在处理数十个传感器和100,000个测量值,因此在每个列/行上循环将花费很长时间......而且经常如果每次测量中只有两个(左右)传感器触发,则绘制的结果很少。出于这个原因,我希望使用单元格数组中的元素只访问数值数组中的正确元素。
有什么想法吗?
答案 0 :(得分:2)
如果我已经很好地理解了问题,那么您似乎无需为输出担心C
。这是代码 -
num_sensors = size(A,2)%// No. of sensors
A = A'; %//' The tracking goes row-wise, so transpose the input array
A(A==-1)=nan; %//set minus 1's to NaNs as excluding elements
out = cell(num_sensors,1); %// storage for ouput
for k1 = 1:num_sensors
%// Per sensor subtractions
per_sensor_subt = bsxfun(@minus,A,A(k1,:));
%// Set all elements of its own row to NaNs to exclude own subtractions
per_sensor_subt(k1,:)=nan;
%// Get all the non-nans that correspond to the valid output
out{k1} = per_sensor_subt(~isnan(per_sensor_subt));
end
输出 -
>> celldisp(out)
out{1} =
10
50
out{2} =
-10
-20
10
40
out{3} =
20
-10
30
out{4} =
-40
-30
-50
正如您已确认每个单元格的输出顺序并不重要,您可以采用更快的简化方法 -
num_sensors = size(A,2)%// No. of sensors
A(A==-1)=nan; %//set minus 1's to NaNs as excluding elements
out = cell(num_sensors,1); %// storage for ouput
for k1 = 1:num_sensors
%// Per sensor subtractions
per_sensor_subt = bsxfun(@minus,A,A(:,k1));
%// Set all elements of its own row to NaNs to exclude own subtractions
per_sensor_subt(:,k1)=nan;
%// Get all the non-nans that correspond to the valid output
out{k1} = per_sensor_subt(~isnan(per_sensor_subt));
end
如果内存允许,完全向量化的解决方案 -
[m,n] = size(A)%// No. of sensors and measurements
A(A==-1)=nan; %//set minus 1's to NaNs as excluding elements
%// Per sensor subtractions
per_sensor_subt = bsxfun(@minus,A,permute(A,[1 3 2]))
%// Set all elements of its own row to NaNs to exclude own subtractions
own_idx = bsxfun(@plus,bsxfun(@plus,[1:m]',[0:n-1]*numel(A)),[0:n-1]*m);%//'
per_sensor_subt(own_idx)=nan;
%// Linear and row-col-dim3 indices of valid subtractions
idx = find(~isnan(per_sensor_subt))
[x,y,z] = ind2sub(size(per_sensor_subt),idx)
%// Get per sensor output
out = arrayfun(@(n) per_sensor_subt(idx(z==n)),1:n,'un',0)
如果您想计算C
,请使用此方法 -
%// Sort A row-wise
[sortedA,sorted_idx] = sort(A,2)
%// Set all invalid indices to zeros, so that later on we can use `nonzeros`
%// to extract out the valid indices
valid_sorted_idx = sorted_idx.*(sortedA~=-1)
%// Convert to a cell array
valid_sorted_idx_cell = mat2cell(valid_sorted_idx,ones(1,size(A,1)),size(A,2))
%// Extract the valid ones(nonzero indices) for the final output, C
C = cellfun(@(x) nonzeros(x), valid_sorted_idx_cell,'un',0)