如何计算矩阵中连续出现的值(正常运行时间)的长度?

Mic*_*l A 5 arrays matlab matrix vectorization

我有这样的数据:

 1     0     1
 1     1     1
 0     1     1
 1     1     1
 1     1     1
 1     1     1
 1     1     0
 1     1     1
 1     1     1
 1     1     1
 1     1     1
 1     1     1
 1     1     1
 1     1     1
 0     0     1
 1     1     1
 1     1     1
 1     1     1
Run Code Online (Sandbox Code Playgroud)

每列代表一个设备,每行代表一个时间段.每个数据点指示设备在该时间段内是否处于活动状态.我正在尝试计算每个设备处于活动状态的每个正常运行时间或"拼写"的长度.换句话说,每列中每个连续法术的长度.在这种情况下,它将2 11 3用于第一列,依此类推.

使用一个设备(单列数据)很容易做到这一点:

rng(1)

%% Parameters
lambda = 0.05;      % Pr(failure)
N = 1;              % number of devices
T = 18;             % number of time periods in sample

%% Generate example data
device_status = [rand(T, N) >= lambda ; false(1, N)];

%% Calculate spell lengths, i.e. duration of uptime for each device
cumul_status = cumsum(device_status);

% The 'cumul_status > 0' condition excludes the case where the vector begins with one
% or more zeros
cumul_uptimes = cumul_status(device_status == 0 & cumul_status > 0);
uptimes = cumul_uptimes - [0 ; cumul_uptimes(1:end-1)];
Run Code Online (Sandbox Code Playgroud)

所以我可以简单地遍历列并一次执行一列并使用parfor(例如)并行运行.有没有办法使用矢量化矩阵运算同时在所有列中执行此操作?

编辑:我应该补充说,由于每个设备可能具有不同数量的正常运行时间,因此这很复杂.

Lui*_*ndo 3

这是一个方法。但不确定它算不算矢量化。

让您的数据矩阵表示为x。然后

[ii, jj] = find([true(1,size(x,2)); ~x; true(1,size(x,2))]);
result = accumarray(jj, ii, [], @(x){nonzeros(diff(x)-1)});
Run Code Online (Sandbox Code Playgroud)

生成一个元胞数组,其中每个元胞对应于一列。在你的例子中,

result{1} =
     2
    11
     3
result{2} =
    13
     3
result{3} =
     6
    11
Run Code Online (Sandbox Code Playgroud)

这是如何运作的

这个想法是找到 中 0 的行索引和列索引x(即true中的值~x),然后使用列索引作为分组变量( 的第一个参数accumarray)。

在每个组中,我们使用匿名函数 @(x){nonzeros(diff(x)-1)}来计算零的行位置的差异。我们可以直接应用,因为得益于 Matlab 的列主diff顺序,列索引find已经排序。我们减去是因为 中的零不计入正常运行时间的一部分;删除等于( )的正常运行时间长度,并将结果向量打包到单元格 ( ) 中。1x0nonzeros{...}

true附加并添加一行值~x以确保我们检测到初始和最终的正常运行时间段。