MATLAB: Usando a interpolação para substituir os valores ausentes (NAN)
-
26-09-2019 - |
Pergunta
Eu tenho uma matriz de células que contêm uma sequência de valores como um vetor de linha. As seqüências contêm alguns valores ausentes representados por NaN
.
Gostaria de substituir todos os Nans usando algum tipo de método de interpolação, como posso fazer isso no MATLAB? Também estou aberto a outras sugestões sobre como lidar com esses valores ausentes.
Considere este exemplo de dados para ilustrar o problema:
seq = {randn(1,10); randn(1,7); randn(1,8)};
for i=1:numel(seq)
%# simulate some missing values
ind = rand( size(seq{i}) ) < 0.2;
seq{i}(ind) = nan;
end
As sequências resultantes:
seq{1}
ans =
-0.50782 -0.32058 NaN -3.0292 -0.45701 1.2424 NaN 0.93373 NaN -0.029006
seq{2}
ans =
0.18245 -1.5651 -0.084539 1.6039 0.098348 0.041374 -0.73417
seq{3}
ans =
NaN NaN 0.42639 -0.37281 -0.23645 2.0237 -2.2584 2.2294
Editar:
Com base nas respostas, acho que houve uma confusão: obviamente não estou trabalhando com dados aleatórios, o código mostrado acima é simplesmente um exemplo de como os dados estão estruturados.
Os dados reais são algum tipo de sinais processados. O problema é que, durante a análise, minha solução falharia se as sequências contivessem valores ausentes, daí a necessidade de filtrar/interpolação (já considerei usar a média de cada sequência para preencher os espaços em branco, mas espero algo mais poderoso)
Solução
Bem, se você estiver trabalhando com dados de séries temporais, poderá usar a função de interpolação incorporada do MATLAB.
Algo assim deve funcionar para a sua situação, mas você precisará adaptar -a um pouco ... ou seja. Se você não tiver uma amostragem espaçada igual, precisará modificar o times
linha.
nseq = cell(size(seq))
for i = 1:numel(seq)
times = 1:length(seq{i});
mask = ~isnan(seq{i});
nseq{i} = seq{i};
nseq{i}(~mask) = interp1(times(mask), seq{i}(mask), times(~mask));
end
Você precisará brincar com as opções de interp1
Para descobrir quais funcionam melhor para sua situação.
Outras dicas
eu usaria inpaint_nans, uma ferramenta projetada para substituir os elementos NAN em matrizes 1-D ou 2-D por interpolação.
seq{1} = [-0.50782 -0.32058 NaN -3.0292 -0.45701 1.2424 NaN 0.93373 NaN -0.029006];
seq{2} = [0.18245 -1.5651 -0.084539 1.6039 0.098348 0.041374 -0.73417];
seq{3} = [NaN NaN 0.42639 -0.37281 -0.23645 2.0237];
for i = 1:3
seq{i} = inpaint_nans(seq{i});
end
seq{:}
ans =
-0.50782 -0.32058 -2.0724 -3.0292 -0.45701 1.2424 1.4528 0.93373 0.44482 -0.029006
ans =
0.18245 -1.5651 -0.084539 1.6039 0.098348 0.041374 -0.73417
ans =
2.0248 1.2256 0.42639 -0.37281 -0.23645 2.0237
Se você tem acesso ao Caixa de ferramentas de identificação do sistema, você pode usar o Misdata função para estimar valores ausentes. De acordo com documentação:
Este comando interpola linearmente os valores ausentes para estimar o primeiro modelo. Em seguida, ele usa esse modelo para estimar os dados ausentes como parâmetros, minimizando os erros de previsão de saída obtidos a partir dos dados reconstruídos.
Basicamente, o algoritmo alterna entre estimar dados ausentes e estimar modelos, de maneira semelhante ao algoritmo de maximização da expectativa (EM).
O modelo estimado pode ser qualquer um dos modelos lineares idmodel
(AR/ARX/..), ou se não for dado, usa um modelo de espaço de estado de ordem padrão.
Veja como aplicá -lo aos seus dados:
for i=1:numel(seq)
dat = misdata( iddata(seq{i}(:)) );
seq{i} = dat.OutputData;
end
Usar GriddedInterpolant
Lá também algumas outras funções, como o Interp1. Para gráficos curvos, o spline é o melhor método para encontrar dados ausentes.
Como diz Judowill, você precisa assumir algum tipo de relação entre seus dados.
Uma opção trivial seria calcular a média da sua série total e usá -las para obter dados ausentes. Outra opção trivial seria tomar a média dos n anteriores e n próximos valores.
Mas tenha muito cuidado com isso: se você está faltando dados, geralmente é melhor para lidar com esses dados ausentes do que compensar alguns dados falsos que podem estragar sua análise.
Considere o seguinte exemplo
X = Algum matriz nx1 y = f (x) com alguns Nans
Em seguida, use
X1 = x (encontre (~ isnan (y))); Y1 = y (encontre (~ isnan (y)));
Agora interpolar sobre x1 e y1 para calcular todos os valores em todos os x.