前提・実現したいこと
pythonで曲線の各点の傾きを表すグラフを作成したいです。
言い換えるならば、x-y の配列・グラフから、x-y’の配列・グラフを求める方法が知りたいということです。
自分なりに配列の微分や勾配の求め方を調べ、numpyのnp.gradientという機能を用いて作成したのですが、x-yの曲線から想像できるような滑らかな曲線とはなりませんでした。
他によりよい方法をご存じの方がいらっしゃいましたらご教授いただけると幸いです。
(今回解析しているのは磁化特性曲線で、横軸の磁界に対する縦軸の磁束の変化率(透磁率)を求めようとしています。)
該当のソースコード
python
1import numpy as np 2import matplotlib.pyplot as plt 3 4x = H[209:416] #磁界の値をxに代入 5y = B[209:416] #磁束の値をyに代入 6 7plt.figure() 8plt.plot(x,y) 9plt.grid() 10 11plt.show()
python
1dx=np.gradient(x) #xの微小分 2dy=np.gradient(y) #yの微小分 3myu=dy/dx #各点の微分した値 4plt.figure() 5plt.plot(x,myu) 6plt.grid() 7 8plt.show()
発生している問題・エラーメッセージ
(画像1)で線形となっている部分が(画像2)のようにギザギザになってしまっています。より適した微分の方法などをご存知でしたら回答よろしくおねがいします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
回答2件
0
【追記】
xの間隔(座標)を考慮すると質問者さんと同じようなグラフになりました。
Python
1dy = np.gradient(y, x) 2plt.plot(x, dy) 3plt.show()
【xの間隔が1の場合】
python
1dy = np.gradient(y) 2plt.plot(x, dy) 3plt.show()
投稿2020/12/01 11:51
編集2020/12/01 13:42総合スコア11137
0
ベストアンサー
Savitzky–Golay法
python
1# 平滑化点数5 2dy5 = np.convolve(y, np.arange(2, -3, -1), 'varid') / 10 3myu5 = dy5 / dx[2:-2] 4 5# 平滑化点数7 6dy7 = np.convolve(y, np.arange(3, -4, -1), 'varid') / 28 7myu7 = dy7 / dx[3:-3] 8 9# 平滑化点数9 10dy9 = np.convolve(y, np.arange(4, -5, -1), 'varid') / 60 11myu9 = dy9 / dx[4:-4] 12 13plt.plot(x, myu, x[2:-2], myu5, x[3:-3], myu7, x[4:-4], myu9) 14plt.grid() 15plt.show()
点数が多いほど平滑化が強くなります
【訂正】
これはxが等間隔じゃないと使えない手法です
データ見たら等間隔ではないので、使えませんね
失礼しました
【追記】
Savitzky-Golay smoothing filter for not equally spaced data
に、不等間隔(non-uniform)でも計算できるSavitzky–Golay法のPythonコードが載ってたので、それを微分(differential)にも使えるように修正しました
よろしければお試しください
python
1import numpy as np 2import math 3 4def non_uniform_savgol_der(x, y, window, polynom, der): 5 """ 6 Applies a Savitzky-Golay filter to y with non-uniform spacing 7 as defined in x 8 9 This is based on https://dsp.stackexchange.com/questions/1676/savitzky-golay-smoothing-filter-for-not-equally-spaced-data 10 The borders are interpolated like scipy.signal.savgol_filter would do 11 12 Parameters 13 ---------- 14 x : array_like 15 List of floats representing the x values of the data 16 y : array_like 17 List of floats representing the y values. Must have same length 18 as x 19 window : int (odd) 20 Window length of datapoints. Must be odd and smaller than x 21 polynom : int 22 The order of polynom used. Must be smaller than the window size 23 der : int 24 The order of derivative. Must be positive and smaller than polynom order 25 26 Returns 27 ------- 28 np.array of float 29 The smoothed y values 30 """ 31 if len(x) != len(y): 32 raise ValueError('"x" and "y" must be of the same size') 33 34 if len(x) < window: 35 raise ValueError('The data size must be larger than the window size') 36 37 if type(window) is not int: 38 raise TypeError('"window" must be an integer') 39 40 if window % 2 == 0: 41 raise ValueError('The "window" must be an odd integer') 42 43 if type(polynom) is not int: 44 raise TypeError('"polynom" must be an integer') 45 46 if polynom >= window: 47 raise ValueError('"polynom" must be less than "window"') 48 49 if polynom < 0: 50 raise ValueError('"polynom" must be larger than 0') 51 52 if type(der) is not int: 53 raise TypeError('"der" must be an integer') 54 55 if der < 0: 56 raise TypeError('"der" must be an positive integer') 57 58 if der > polynom: 59 raise TypeError('"der" must be equal or less than "polynom"') 60 61 half_window = window // 2 62 polynom += 1 63 64 # Initialize variables 65 A = np.empty((window, polynom)) # Matrix 66 tA = np.empty((polynom, window)) # Transposed matrix 67 t = np.empty(window) # Local x variables 68 y_smoothed = np.full(len(y), np.nan) 69 70 # Start smoothing 71 for i in range(half_window, len(x) - half_window, 1): 72 # Center a window of x values on x[i] 73 for j in range(0, window, 1): 74 t[j] = x[i + j - half_window] - x[i] 75 76 # Create the initial matrix A and its transposed form tA 77 for j in range(0, window, 1): 78 r = 1.0 79 for k in range(0, polynom, 1): 80 A[j, k] = r 81 tA[k, j] = r 82 r *= t[j] 83 84 # Multiply the two matrices 85 tAA = np.matmul(tA, A) 86 87 # Invert the product of the matrices 88 tAA = np.linalg.inv(tAA) 89 90 # Calculate the pseudoinverse of the design matrix 91 coeffs = np.matmul(tAA, tA) 92 93 # Calculate c0 which is also the y value for y[i] 94 y_smoothed[i] = 0 95 for j in range(0, window, 1): 96 #y_smoothed[i] += coeffs[0, j] * y[i + j - half_window] 97 y_smoothed[i] += coeffs[der, j] * y[i + j - half_window] * math.factorial(der) 98 99 # If at the end or beginning, store all coefficients for the polynom 100 if i == half_window: 101 first_coeffs = np.zeros(polynom) 102 for j in range(0, window, 1): 103 for k in range(polynom): 104 first_coeffs[k] += coeffs[k, j] * y[j] 105 elif i == len(x) - half_window - 1: 106 last_coeffs = np.zeros(polynom) 107 for j in range(0, window, 1): 108 for k in range(polynom): 109 last_coeffs[k] += coeffs[k, j] * y[len(y) - window + j] 110 111 # Interpolate the result at the left border 112 for i in range(0, half_window, 1): 113 y_smoothed[i] = 0 114 x_i = 1 115 #for j in range(0, polynom, 1): 116 for j in range(der, polynom, 1): 117 y_smoothed[i] += first_coeffs[j] * x_i * math.factorial(j) 118 x_i *= x[i] - x[half_window] 119 120 # Interpolate the result at the right border 121 for i in range(len(x) - half_window, len(x), 1): 122 y_smoothed[i] = 0 123 x_i = 1 124 #for j in range(0, polynom, 1): 125 for j in range(der, polynom, 1): 126 y_smoothed[i] += last_coeffs[j] * x_i * math.factorial(j) 127 x_i *= x[i] - x[-half_window - 1] 128 129 return y_smoothed 130 131if __name__ == '__main__': 132 import numpy as np 133 import matplotlib.pyplot as plt 134 135 # テスト用ダミーデータ 136 x = np.arange(0, 10, 0.1) 137 y = 2 * x * x + 3 * x + 4 + np.random.randn(100) / 10 138 y11 = non_uniform_savgol_der(x, y, 11, 2, 0) 139 plt.plot(x, y, x, y11) 140 plt.grid() 141 plt.show() 142 143 # 微分 144 dy = np.gradient(y, x) 145 dy11 = non_uniform_savgol_der(x, y, 11, 2, 1) 146 plt.plot(x, dy, x, dy11) 147 plt.grid() 148 plt.show() 149 150 # 二階微分 151 ddy = np.gradient(dy, x) 152 ddy11 = non_uniform_savgol_der(x, y, 11, 2, 2) 153 plt.plot(x, ddy, x, ddy11) 154 plt.grid() 155 plt.show()
xが順番に並んでないのは、sortすれば直せます
python
1# テスト用ダミーデータ 2x = np.array([1, 2, 3, 5, 4, 6]) 3y = x * 2 4print(x) 5print(y) 6 7# ソート (xの順番でyも) 8tmp = zip(x, y) 9tmp2 = sorted(tmp) 10xx, yy = zip(*tmp2) 11xx = np.array(xx) 12yy = np.array(yy) 13 14# 比較 15print(x) 16print(xx) 17print(y) 18print(yy)
投稿2020/12/01 11:46
編集2020/12/05 02:33総合スコア7658
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。




2020/12/01 12:14
2020/12/01 12:17
2020/12/01 12:27
2020/12/01 12:52
2020/12/01 17:30
2020/12/02 00:37
2020/12/02 05:43