2013-11-13 3 views
1

Предположит, что у вас есть последовательность значений X/Y, где есть «разрыв» ...Заменить отсутствующие значения от Gap в последовательности

resolution = 0.1; 
x = [0:resolution:10 10.5:resolution:20]; % 4 missing values (10.1, 10.2, 10.3, 10.4) 
y = ones(1, length(x)); 

Как вы можете определить «разрыв» в последовательности и заменить он с некоторым типом значения (например, замените его на 0)?

Я думаю, что это работает, но мне интересно, есть ли лучший способ. Кроме того, этот метод будет работать только для 1 разрыва (а не для нескольких промежутков). Я надеюсь на более простой метод ... может быть, даже метод без цикла.

xDiff = diff(x); 
calcResolution = min(xDiff); % Try to calculate original resolution 
newY = y; 
newX = x; 

thresh = 0.000001; 
for i=1:length(xDiff) 
    % Check any time the difference is larger than our resolution... 
    if (abs(xDiff(i) - calcResolution) > thresh) 
     gapSize = (xDiff(i)/calcResolution) - 1; 
     newY = [y(1:i) zeros(1, gapSize) y(i:end)]; 
     newX = [x(1:i) (x(i) + calcResolution):calcResolution:x(i+1) x((i+1):end)]; 
    end 
end 

% newX == 0:resolution:20 
% newY == [1 1 1 1 1 1 1 ... 0 0 0 0 ... 1 1 1 1 1 1 1] 
+1

Когда есть пробел, как вы определяете, сколько значений отсутствует? Каким должен быть шаг? –

+0

@ LuisMendo Хороший вопрос. Мне нужно было бы рассчитать шаг. Я использовал наименьшее значение в diff(), но мне также нравится идея использования 'mode()' из приведенного ниже ответа. – user807566

ответ

1
%Assumes the most frequent difference is the resolution 
calcResoultion = mode(diff(x)); 

%Create data set with no gaps 
xMin = min(x); 
xMax = max(x); 
noGapData = [xMin:calcResolution:xMax]; 

%Create full length of y data 
y = ones(1,length(noGapData)); 

%Round data to mitigate number precision issues from comment 
noGapData = round(noGapData * 100)/100; 
x = round(x * 100)/100; 

%Find values in noGapData that are not in x 
missingValues = setdiff(noGapData,x); 

%Replace 1 with 0 at indicies of missing (gap) values 
y(find(ismember(noGapData,missingValues))) = 0; 

петель и будет работать для данных с любым количеством пробелов (предполагается, что число зазоров меньше, чем число точек данных в последовательности, чтобы гарантировать, что mode(diff(x)) возвращает правильное разрешение.

+1

Это не работает, 'missingValues' возвращает каждое значение' noGapData', кроме 0. – David

+2

Возможно, это проблема с числовой точностью, мне придется дополнительно исследовать. Документация выглядит так: 'missingValues' должен содержать только значения« gap ». – DaveH

+1

@ Давид был прав насчет моего первоначального ответа. Теперь я проверил этот код с добавлением округления данных, и он идентифицирует [10.1, 10.2, 10.3, 10.4] как недостающие значения – DaveH

1

Это должно работать, считая, что (как и DaveH) наиболее часто возникающий разрыв между элементами - это разрешение, и, кроме того, x в порядке возрастания. Это не очень хороший код, и я уверен, что его можно было бы улучшить, но, по крайней мере, (Думаю) работает

d=diff(x); 
gapStart=find((d-mode(d))>1e-10); 
gap=[x(gapStart);x(gapStart+1)]; 
gapLength=cumsum(diff(gap)/resolution); 
xNew=0:resolution:max(x); 
yNew=zeros(size(xNew)); 
yNew(1:gapStart(1))=y(1:gapStart(1)); 
for i=1:length(gapStart)-1 
    yNew(gapStart(i)+gapLength(i)+1-i:gapLength(i)+gapStart(i+1)-i)=y(gapStart(i)+1:gapStart(i+1)); 
end 
yNew(gapStart(end)+gapLength(end)-i:end)=y(gapStart(end)+1:end) 
Смежные вопросы