Apply average smoothing to data from text file?

2 vues (au cours des 30 derniers jours)
Zoe Zontos
Zoe Zontos le 9 Oct 2016
Modifié(e) : Star Strider le 11 Oct 2016
I have tried looking up various way to take my data from a text file and apply a smoothing/moving average filter (without a loop), but NOTHING I do seems to work. I may be completely approaching this wrong, but any help in the right direction would be appreciated!
The file I am working with is attached: SN_d_tot_V2.txt
This is my latest attempt, and while it finally gives me a plot display, it doesn't give me the original data or the smoothed data:
if true
ssnmatrix = dlmread('SN_d_tot_V2.txt'); %data has been truncated to only show 1849-2015
Q = size(ssnmatrix);
nrows = Q(1);
ncolumns = Q(2);
n = 365/2;
ssnave = ssnraw;
ssnave = ssnave/(2*n+1);
% pick out the two relevant columns
decyear = ssnmatrix(:,4);
ssnraw = ssnmatrix(:,5);
% attempt to create filter coefficients
a = 1;
b = [2 1];
%smooth data and plot
y = filter(b,a,ssnave);
t = 1:length(ssnave);
plot(t,decyear,ssnraw,ssnave)
end
Could anyone possible explain what I'm doing wrong? I simply want to smooth the data and get my plot!
  3 commentaires
Star Strider
Star Strider le 9 Oct 2016
What do you want to do with your signal?
Are there frequency components you want to filter out?
Moving average filters are rarely a good choice for signal processing.
Zoe Zontos
Zoe Zontos le 9 Oct 2016
Modifié(e) : Zoe Zontos le 9 Oct 2016
I guess the simplest way to put it is that I want to take my data and average n adjacent values, and to plot the average. The other way the data was smoothed is as follows:
if true
clear;
clc;
ssnmatrix = dlmread('SN_d_tot_V2.txt'); %data has been truncated to only show 1849-2015
Q = size(ssnmatrix);
nrows = Q(1);
ncolumns = Q(2);
% pick out the two relevant columns
decyear = ssnmatrix(:,4);
ssnraw = ssnmatrix(:,5);
% Smooth the data set
% create a centered average of half width n
% monthly average n=15
% yearly average n=365/2
n = 365/2;
ssnave = ssnraw;
for shift = 1:n
ssnave = ssnave + circshift(ssnraw,[shift,0]) + circshift(ssnraw,[-shift,0]);
end
ssnave = ssnave/(2*n+1);
% Plot raw data and smoothed data
figure(1)
plot(decyear,ssnraw,decyear,ssnave);
ylabel('SSN')
xlabel('Time (Years)')
title('Sunspot Numbers from 1849-2015 with Smoothing')
end
Which results in a plot of:

Connectez-vous pour commenter.

Réponse acceptée

Image Analyst
Image Analyst le 9 Oct 2016
I'm not saying this is the best, but you can try this:
data = importdata('SN_d_tot_V2.txt');
col4 = data(:,4);
col5 = data(:,5);
t = 1:length(col4);
plot(t, col4, 'r-', 'LineWidth', 2);
hold on;
plot(t, col5, 'b-', 'LineWidth', 2);
grid on;
order = 2;
frameLength = 901; % <=== Adjust this to get different levels of smoothing.
smoothCol4 = sgolayfilt(col4, order, frameLength);
smoothCol5 = sgolayfilt(col5, order, frameLength);
plot(t, smoothCol4, 'm-', 'LineWidth', 4);
plot(t, smoothCol5, 'c-', 'LineWidth', 4);
  8 commentaires
Zoe Zontos
Zoe Zontos le 10 Oct 2016
Sorry, to ask for help again, but if anyone knows whether the data set I've provided results in revealing that there is, in fact, an 11-year cycle that is evident once applying an FFT to the data set, then please just verify for me. I have tried multiple ways to use FFT but nothing is giving me an 10-11 year max in cycle frequency for this data set..
Image Analyst
Image Analyst le 10 Oct 2016
How about just using findpeaks() on the smoothed signal and then using diff() on the peak locations (x axis = years) and seeing what the average difference between peak years is?

Connectez-vous pour commenter.

Plus de réponses (3)

Star Strider
Star Strider le 10 Oct 2016
Modifié(e) : Star Strider le 11 Oct 2016
My filter approach was correct. It works to filter out the noise and smooth the signal. Also, the 11-year period is obvious if you plot it as a period and not as frequency.
The Code:
d = load('Zoe Zontos SN_d_tot_V2.txt');
t = d(:,4); % Time
sn = d(:,5); % Sunspot Numbers
L = size(sn,1);
tsts = [mean(diff(t)) std(diff(t)) min(t) max(t)];
figure(1)
plot(t, sn)
grid
Ts = tsts(1); % Sampling Interval (Approximate)
Fs = 1/Ts; % Sampling Frequency (Appriximate)
Fn = Fs/2; % Nyquist Frequency (Approximate)
FTsn = fft(sn)/L; % Fourier Transform
Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
Iv = 1:length(Fv); % Index Vector
% % Fvi = [NaN 1./Fv(2:end)];
Wp = 1/Fn; % Normalised Passband
Ws = 1.5/Fn; % Normalised Stopband
Rp = 20; % Passband Ripple
Rs = 40; % Stopband Ripple
[n,Wn] = buttord(Wp,Ws,Rp,Rs); % Filter Order
[b,a] = butter(n,Wn); % Filter Transfer Function Coefficients
[sos,g] = tf2sos(b,a); % Second-Order-Section For Stability
snf = filtfilt(sos,g,sn); % Phase-Neutral Filtering
figure(3)
freqz(sos) % Bode Plot
figure(2)
semilogy(Fv, abs(FTsn(Iv))*2)
grid
axis([0 25 ylim])
xlabel('Frequency (Y)')
figure(4)
plot(t, sn)
hold on
plot(t, snf, '-r', 'LineWidth',2)
hold off
grid
FTsnf = fft(snf)/L; % Fourier Transform Of Filtered Signal
[sn_max,max_idx] = max(abs(FTsnf(Iv(2:end)))*2);
figure(5)
plot(1./Fv, abs(FTsnf(Iv))*2)
grid
axis([0 15 0 60])
xlabel('Period (Years/Cycle)')
text(1./Fv(max_idx+1), sn_max, sprintf('Mean Number %.2f\nMean Period %.2f years', sn_max, 1./Fv(max_idx+1)), 'HorizontalALignment','center', 'VerticalAlignment','bottom')
The Plots:
EDIT Corrected units of x-axis label to ‘Years/Cycle’ in second plot figure and code.

Image Analyst
Image Analyst le 9 Oct 2016
You forgot to attach 'SN_d_tot_V2.txt', in case people want to test their code. How do you want to smooth? Personally I'd use conv:
smoothed = conv(ssnraw, ones(1,3)/3, 'same');
But there are other options like different window sizes, sgolayfilt(), etc.
  1 commentaire
Zoe Zontos
Zoe Zontos le 9 Oct 2016
Modifié(e) : Zoe Zontos le 9 Oct 2016
Sorry about that, I attached the file now and updated what I tried doing! And I just want to do a general smoothing of the data or a moving average, just any other way of smoothing that doesn't require a loop of any kind because I am looking for alternative ways.

Connectez-vous pour commenter.


Guillaume
Guillaume le 9 Oct 2016
As per the documentation of filter, the coefficient b for a moving average filter is:
b = (1/windowSize)*ones(1,windowSize);
All values of b must be equal and their product must be 1 for it to be a moving average filter.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by