Mayank Lakhani
Mayank Lakhani

Reputation: 193

Smoothing the curve

Below is my code for the plot. How to make the plot more smoother.

len1 = [25, 250, 500, 750, 1000];
for k1 = 1:length(len1)
    standard_deviation1(k1) = std(resdphs(1:5000, len1(k1)));
end

f10 = [110, 100, 90, 80, 70];
figure(3),plot(f10, standard_deviation1);xlabel('frequency'); ylabel('standarddev');

gridenter image description here

Upvotes: 0

Views: 276

Answers (1)

rayryeng
rayryeng

Reputation: 104555

As stated in the comments, you can first try to apply a moving average to your data which applies local smoothing to overlapping windows in your data. However, for this to be successful, you must have a higher point density to achieve good smoothing. Currently, your plot only has a few points uniformly spaced at 500 units and so moving average will significantly alter the way the plot looks. I'll show you an example soon.

Let's get back to the method at hand. First, apply linear interpolation between each of the points to get a higher point density. After you apply linear interpolation, you can apply the moving average operation with conv. However, what will happen is that in between your keypoints will exist artificial data that isn't representative of your problem. I'd also like to mention that this plot is for aesthetic purposes and the data in between the keypoints should not be used for any critical decisions.

If you simply want to plot the points, consider not using plot and using stem instead. In any case, use interp1 as the base method for interpolating in between the keypoints. Once you do that, you can apply a moving average by convolution - specifically, use a kernel that has a small amount of filter taps that are all equally weighted. Something like a 5-tap window or 7-tap window may suffice.

Using the variables that you declared above:

%// Specify number of total points
num_points = 300;

%// Specify moving average window
move_size = 7;

%// Specify interpolated y coordinates
xpts = linspace(min(f10), max(f10), num_points);
out = interp1(f10, standard_deviation1, xpts, 'linear');

%// Apply moving average
kernel = (1/move_size)*(ones(1,move_size));
out_smooth = conv(out, kernel, 'same');

%// Also apply moving average on the raw data itself for demonstration
out_smooth_raw = conv(standard_deviation1, kernel, 'same');

%// Plot everything
plot(f10, standard_deviation1, f10, out_smooth_raw, 'x-', xpts, out_smooth);
legend('Original Data', 'Smoothed Data - Raw', 'Smoothed Data - Interpolated');

Let's do this with some example data:

f10 = 0 : 500 : 5000;
rng(123); %// Set seed for reproducibility
standard_deviation1 = rand(1,numel(f10));

Using the above data and with the above code, we get this plot:

enter image description here

As you can see, applying a moving average on your data without interpolation significantly alters the data because of the resolution. If you apply interpolation first, then apply a moving average, you will see that you get a somewhat better representation of your original data with the corners smoothed. Bear in mind that the data at the beginning and at the end of the smoothened result will be meaningless as you would be taking the moving average of windows with zeros padded into the data to allow the calculations to work.

Upvotes: 4

Related Questions