GK89
GK89

Reputation: 664

Function to simply smooth data

I am unsure of how to write this function and need help on how to write it. I have a 1D array of data and a list. When plotting the data it looks like this: enter image description here

The list contains the index of the array where the step change occurs. In this case, the list contains one item and its value is 34. I would like the function to smooth the data in the array by replacing it with a straight line, from array[0] to array[34] (the item in the list) then smooth the remaining data points from array[35] to array[n].

This is a simple example of the data, but it can get more complicated as there may be multiple step changes. This is a pseudocode,but again, I have no idea how to write it.

def funcx (x, list_):
    for each set of points between list items
    replace with linear line
return(updated array) 

Here is the array

x = [515.294128, 513.52941899999996, 517.05883800000004, 514.70593299999996, 518.23535200000003, 516.470642, 520.52630599999998, 520.0, 523.15783699999997, 523.15783699999997, 526.31573500000002, 525.26312299999995, 532.94116199999996, 543.68420400000002, 538.823486, 533.52941899999996, 540.52630599999998, 541.05267300000003, 541.05267300000003, 543.15789800000005, 545.26318400000002, 544.21057099999996, 546.84210199999995, 547.89477499999998, 548.94738800000005, 550.35717799999998, 550.714294, 551.42858899999999, 553.92858899999999, 556.785706, 548.94738800000005, 555.35717799999998, 571.90478499999995, 578.09521500000005, 97.647041000000002, 100.0, 101.333336, 101.333336, 101.333336, 103.333336, 108.0, 108.0, 110.0, 110.0, 112.85714, 113.571426, 117.14286, 116.428574, 120.0, 120.0, 120.5, 121.25, 121.25, 123.125, 126.25, 127.5, 129.375, 132.30767800000001, 133.84612999999999, 135.38459800000001, 134.61537200000001, 136.92306500000001, 135.38459800000001, 137.69229100000001, 142.5, 143.125, 146.25, 146.25, 148.125, 149.375, 149.99998500000001, 150.833313, 153.333313, 154.166641, 154.166641, 154.166641, 154.166641, 161.0, 161.0, 169.5, 169.5, 177.777725, 178.88883999999999, 180.625, 181.25, 183.75, 183.75, 185.0, 186.25, 186.25, 188.75, 188.125, 186.875, 188.125, 190.666687, 191.333359, 195.333359, 197.333359, 198.666687, 198.00001499999999, 198.00001499999999, 199.333359, 199.333359, 200.833313, 204.99998500000001, 209.166641, 211.42854299999999, 212.85711699999999, 214.28568999999999, 217.14283800000001, 215.71426400000001, 218.57141100000001, 217.85711699999999, 219.28568999999999, 220.66665599999999, 221.99998500000001, 220.66665599999999, 219.99998500000001, 223.99998500000001, 225.99998500000001, 227.333313, 228.66665599999999, 231.333313, 232.66665599999999, 233.333313, 235.333313, 233.99998500000001, 234.66665599999999, 236.66665599999999, 239.333313, 241.666687, 241.666687, 244.166687, 245.83334400000001, 247.50001499999999, 249.166687, 251.42854299999999, 251.42854299999999, 254.99996899999999, 254.28568999999999, 258.57141100000001, 259.285706, 259.285706, 261.875, 259.285706, 261.875, 264.375, 266.875]

Upvotes: 0

Views: 138

Answers (1)

Mr. T
Mr. T

Reputation: 12410

You can employ np.polyfit with order 1, i.e., a linear function, and np.polyval for this task:

import numpy as np
#linear fit function for an array
def smoothline(arr):
    n = np.arange(len(arr))
    #retrieve the polynomial coefficients of a least-square fit
    fit = np.polyfit(n, arr, 1)
    #return the array with fitted data points
    return np.polyval(fit, n)

raw_arr = np.asarray( [515.294128, 513.52941899999996, 517.05883800000004, 514.70593299999996, 518.23535200000003, 516.470642, 520.52630599999998, 520.0, 523.15783699999997, 523.15783699999997, 526.31573500000002, 525.26312299999995, 532.94116199999996, 543.68420400000002, 538.823486, 533.52941899999996, 540.52630599999998, 541.05267300000003, 541.05267300000003, 543.15789800000005, 545.26318400000002, 544.21057099999996, 546.84210199999995, 547.89477499999998, 548.94738800000005, 550.35717799999998, 550.714294, 551.42858899999999, 553.92858899999999, 556.785706, 548.94738800000005, 555.35717799999998, 571.90478499999995, 578.09521500000005, 97.647041000000002, 100.0, 101.333336, 101.333336, 101.333336, 103.333336, 108.0, 108.0, 110.0, 110.0, 112.85714, 113.571426, 117.14286, 116.428574, 120.0, 120.0, 120.5, 121.25, 121.25, 123.125, 126.25, 127.5, 129.375, 132.30767800000001, 133.84612999999999, 135.38459800000001, 134.61537200000001, 136.92306500000001, 135.38459800000001, 137.69229100000001, 142.5, 143.125, 146.25, 146.25, 148.125, 149.375, 149.99998500000001, 150.833313, 153.333313, 154.166641, 154.166641, 154.166641, 154.166641, 161.0, 161.0, 169.5, 169.5, 177.777725, 178.88883999999999, 180.625, 181.25, 183.75, 183.75, 185.0, 186.25, 186.25, 188.75, 188.125, 186.875, 188.125, 190.666687, 191.333359, 195.333359, 197.333359, 198.666687, 198.00001499999999, 198.00001499999999, 199.333359, 199.333359, 200.833313, 204.99998500000001, 209.166641, 211.42854299999999, 212.85711699999999, 214.28568999999999, 217.14283800000001, 215.71426400000001, 218.57141100000001, 217.85711699999999, 219.28568999999999, 220.66665599999999, 221.99998500000001, 220.66665599999999, 219.99998500000001, 223.99998500000001, 225.99998500000001, 227.333313, 228.66665599999999, 231.333313, 232.66665599999999, 233.333313, 235.333313, 233.99998500000001, 234.66665599999999, 236.66665599999999, 239.333313, 241.666687, 241.666687, 244.166687, 245.83334400000001, 247.50001499999999, 249.166687, 251.42854299999999, 251.42854299999999, 254.99996899999999, 254.28568999999999, 258.57141100000001, 259.285706, 259.285706, 261.875, 259.285706, 261.875, 264.375, 266.875])
n = len(raw_arr)
smooth_arr = raw_arr.copy()
#predefined breakpoints, for demonstration I added another "break" point
breaks = [34, 87]
#create list of segments from break list and length of the raw data array
segments = [(i, j) for i, j in zip([0] + breaks, breaks + [n])]
#cycle through each array segment
for start, stop in segments:
    #fit each array segment
    smooth_arr[start:stop] = smoothline(raw_arr[start:stop])

#plot raw and fitted array    
plt.plot(np.arange(n), raw_arr, label = "raw")
plt.plot(np.arange(n), smooth_arr, label = "smooth")
plt.legend(loc = "best")
plt.show()

Output:

enter image description here

Upvotes: 1

Related Questions