Перемещение окна с двумя условиями - Matlab - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть данные временного ряда с амплитудой диапазона значений от 1 до 100. Мне нужно использовать движущееся окно (продолжительность 10 секунд) и пометить / выделить сегменты данных, которые попадают с пороговым диапазоном 91до 97 в течение не менее 10 секунд или более. Данные доступны по следующей ссылке

https://www.dropbox.com/s/fx7z9qzg8gxb4x3/data.mat?dl=0

Любая помощь в этом отношении высоко ценится.

Я использовал следующий код:

`x= load('data.mat');
time = 1:length(x);
window = 1000; % 10 second window - data was sampled at 100Hz.
[TF,L,U,C] = isoutlier(x); % I tried to find outlier
figure;
plot(time,x,time(TF),x(TF),'*')
legend('Data','Outlier')
figure;
plot(time,x,time(TF),x(TF),'x',time,93*ones(1,length(x)),time,
97*ones(1,length(x)))`

Я получаю следующую цифру [https://i.stack.imgur.com/fZa9m.jpg] Но не уверен. Как использовать это как пороговые окна.

Заранее спасибо

1 Ответ

1 голос
/ 06 ноября 2019

Вероятно, есть способ сделать это с реальным скользящим окном, но, поскольку мне приходилось выполнять какие-то подобные операции с вами по-другому, я буду повторно использовать функцию, которую я делал несколько лет назад, которая идеально подходит для этогопроблема в другом направлении.

В основном процесс выглядит так:

  • Найти ВСЕ индексы, подтверждающие условие (x> 91 и x <97). </li>
  • Найти началои остановите индексы каждой последовательной группы / интервала, найденного в шаге выше.
  • Вычислите длину каждого интервала (легко с запуском и остановкой, указанными выше)
  • Сбросьте слишком короткие интервалы

К настоящему времени у вас есть список интервалов (индексы запуска и остановки), проверяющих все ваши условия (уровень сигнала И длительность). Теперь вы можете:

  • перестроить один вектор действительных индексов
  • Создать вторичный вектор, который содержит только помеченные данные (данные x, которые подтвердили все условия).
  • display: -)

В коде это выглядит так:

%% Your inputs
load('data.mat');
time = 1:length(x);

%% Setup
winSize = 1000 ;    % Fs * Duration = 100 * 10 = 1000 points
lvlmin = 91 ;       % Minimum level to flag
lvlmax = 97 ;       % Maximum level to flag

%% Find which interval to flag
% find all the indices where the condition is true
idx = ( x>lvlmin ) & ( x<lvlmax ) ;
% get the start and stop index of each group of consecutive indices
itBounds = get_interval_boundaries( idx ) ;
% get the length of each interval/group
itLenght = diff(itBounds,1,2)+1 ; 
% only consider intervals >= winSize
it2flag = itLenght >= winSize ; 
nint = sum(it2flag) ;       % found 241 valid intervals out of 596.

%% Clear [idx] of the short intervals
itbad = itBounds( ~it2flag , : ) ; % keep only the intervals to discard
for k=1:size(itbad,1)
    idx(itbad(k,1):itbad(k,2)) = false ;
end

%% Display
flaggedTime = time(idx) ;
flaggedData = x(idx) ;

figure
plot(time,x)
hold on
plot(flaggedTime,flaggedData,'.')

lx = [time(1) time(end)] ;
plot( lx , [lvlmin lvlmin], '-.k')
plot( lx , [lvlmax lvlmax], '-.k')

%% OR, alternatively, keep vectors the same lenght by adding NaNs
flaggedData = x ;
flaggedData(~idx) = NaN ;

figure
plot(time,x)
hold on
plot(time,flaggedData)

И предварительный просмотр того, как данные помечены: enter image description here


Вам понадобится код для get_interval_boundaries.m. Я мог бы закодировать только функциональность, необходимую в меньшем количестве кода, но, поскольку он был доступен и отлично работает, нет необходимости заново изобретать колесо:

function itbound = get_interval_boundaries(vec)
% function itbound = get_interval_boundaries(vec)
%
% This function takes a vector of index as input (or a logical index array)
% It returns a nx2 table containing on each line the first and last index
% of consecutive intervals of indexes.
% ex:
% A = [1 2 3 5 7 8 9] ;
% [itbound] = get_interval_boundaries(A)
% itbound =
%      1     3
%      5     5
%      7     9
% 
% 09-Oct-2011 - Hoki:  creation
% 15-Sep-2012 - Hoki: Corrected last index special case
%                       (return last idx instead of 0)
% 01-Sep-2014 - Hoki: Corrected first index special case
%                       (return [1 1] in case vec is a scalar)

%% Check vec type (logical array or direct indexing)

% Return empty vector if input is empty
itbound = [] ;
if isempty(vec)
    return
end

% Check the type of input vector
if islogical(vec)
    idxDirect = find(vec) ;

elseif isnumeric(vec)
    idxDirect = vec ;
else
    errordlg('bad type for ''vec''. Variable should be numeric or logical',mfilename,'modal')
    return
end

%% Detect intervals
Npts = length(idxDirect) ;

% return [] in case vec is all [0]
if Npts == 0 ; return ; end

itbound(1,1) = idxDirect(1) ;
% return [x x] in case vec is a scalar value [x]
if Npts == 1
    itbound(1,2) = idxDirect(1) ;
    return
end

j=1 ;
for k = 2:Npts
    if idxDirect(k)==idxDirect(k-1)+1
        if k~=Npts
            % Cycle the loop
            continue
        else
            % Last point: Assign closing boundary of last interval
            itbound(j,2) = idxDirect(k) ;
        end
    else
        % Assign closing boundary of current interval
        itbound(j,2) = idxDirect(k-1) ;
        % Assign opening boundary of next interval
        j = j + 1 ;
        itbound(j,1) = idxDirect(k) ;
        % If we're on the very last index, close the interval.
        if k==Npts
            itbound(j,2) = idxDirect(k) ;
        end
    end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...