Apply average smoothing to data from text file?

2 ビュー (過去 30 日間)
Zoe Zontos
Zoe Zontos 2016 年 10 月 9 日
編集済み: Star Strider 2016 年 10 月 11 日
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 件のコメント
Star Strider
Star Strider 2016 年 10 月 9 日
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 2016 年 10 月 9 日
編集済み: Zoe Zontos 2016 年 10 月 9 日
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:

サインインしてコメントする。

採用された回答

Image Analyst
Image Analyst 2016 年 10 月 9 日
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 件のコメント
Zoe Zontos
Zoe Zontos 2016 年 10 月 10 日
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 2016 年 10 月 10 日
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?

サインインしてコメントする。

その他の回答 (3 件)

Star Strider
Star Strider 2016 年 10 月 10 日
編集済み: Star Strider 2016 年 10 月 11 日
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 2016 年 10 月 9 日
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 件のコメント
Zoe Zontos
Zoe Zontos 2016 年 10 月 9 日
編集済み: Zoe Zontos 2016 年 10 月 9 日
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.

サインインしてコメントする。


Guillaume
Guillaume 2016 年 10 月 9 日
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