🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

10674閲覧

pythonで曲線の各点の傾きを表すグラフを作成したいです

KNKR

総合スコア1

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2020/12/01 09:58

前提・実現したいこと

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()

各点の傾きを求めたい曲線(画像1)
各点の傾きを求めたい曲線(画像1)

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()

試作したグラフ(画像2)
試作したグラフ(画像2)

発生している問題・エラーメッセージ

(画像1)で線形となっている部分が(画像2)のようにギザギザになってしまっています。より適した微分の方法などをご存知でしたら回答よろしくおねがいします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2020/12/01 10:54

データは提示出来ますか?
KNKR

2020/12/01 11:03

xとyのリストでよろしいでしょうか x array([-397.675275 , -396.95099758, -396.11310802, -395.6775948 , -395.56398266, -395.45037051, -394.75449613, -394.32371675, -393.83139746, -394.55094104, -394.06335559, -393.88820353, -393.2822721 , -391.63489601, -388.74725402, -387.07147489, -385.62292006, -384.46786326, -381.3198601 , -379.75769312, -379.29851071, -378.20025998, -375.01911995, -371.84271376, -371.2935884 , -369.44265722, -365.7455287 , -364.64727797, -362.54071947, -358.23292568, -356.47193744, -353.95826876, -350.17119729, -348.95933442, -343.72844196, -341.70709256, -339.39697897, -335.40635241, -333.96253142, -328.67483288, -326.10435812, -321.59774308, -318.97046225, -314.54905631, -311.77502646, -307.67078776, -304.60799371, -299.11674009, -296.14388898, -292.15326243, -288.45613391, -282.85126814, -278.4298622 , -275.4570111 , -269.09946487, -265.83311573, -260.77737533, -255.25771867, -250.72270058, -246.27289161, -240.6396228 , -235.92945267, -231.21928253, -226.33869418, -221.68533012, -216.16567345, -210.7075567 , -207.4696106 , -201.9215509 , -196.52024022, -192.5343475 , -187.21824593, -181.89741052, -177.2487803 , -171.81433274, -165.05441017, -160.83655933, -156.32994428, -149.83038288, -143.96515595, -139.65736215, -133.65012004, -126.45468425, -120.1539441 , -115.93609326, -111.02710187, -104.90151377, -99.5854122 , -92.73554668, -87.79341842, -82.70927498, -76.35172875, -70.6048478 , -64.04374649, -58.03650437, -52.22808351, -45.69775215, -40.12128942, -33.56255502, -27.87058661, -22.03423609, -16.14013274, -10.44816433, -4.72731949, 1.45583209, 5.67434567, 12.03047175, 18.73406162, 23.27002647, 29.51112025, 34.97160392, 41.79069948, 46.26891149, 51.73176208, 58.52008768, 64.73088489, 71.55234737, 76.37612965, 82.84728802, 89.29004335, 94.66295099, 101.07730329, 107.23129442, 113.70718663, 118.53096891, 124.39619584, 130.98570019, 136.70417811, 139.94212421, 146.55529776, 152.25010648, 158.37569457, 163.05272783, 168.14160512, 174.32399929, 179.753713 , 183.99996688, 191.02498445, 196.74346237, 200.96131321, 206.65612193, 211.82547448, 215.98651926, 221.16060565, 226.44830418, 230.46259994, 235.43313124, 239.96814932, 244.04398498, 249.96601799, 254.93654929, 258.48692879, 264.58411385, 268.60314344, 272.4138841 , 278.33591711, 282.87566903, 285.96686611, 290.7906484 , 295.09370835, 300.18258563, 302.98501852, 308.24431402, 311.01834387, 315.49655587, 318.7013651 , 323.70029944, 324.48138293, 329.74067843, 331.06615344, 335.17039214, 338.75390852, 340.45809068, 344.96470572, 345.68898314, 349.67487586, 353.25839223, 354.29983689, 358.22892353, 360.45382802, 363.36987305, 367.0954046 , 368.36880738, 369.49546115, 372.12274198, 374.66954754, 375.90981344, 377.64239864, 381.25431805, 382.61292994, 383.30880432, 383.88633272, 386.42840444, 388.94207313, 390.49950627, 390.01192081, 389.89357483, 390.96342252, 391.16697761, 393.33034219, 394.40018988, 396.04756596, 396.85705249, 397.51979 , 397.75174812, 397.69494205, 397.92690018])
KNKR

2020/12/01 11:03

y array([-0.73150471, -0.73149759, -0.73151854, -0.73153669, -0.7315366 , -0.73153791, -0.73153641, -0.73152649, -0.73153622, -0.7315726 , -0.73166932, -0.73164116, -0.73169157, -0.73171673, -0.73179381, -0.73184703, -0.73189885, -0.73195628, -0.73197583, -0.73202624, -0.73206684, -0.73213549, -0.73218871, -0.73226158, -0.73227271, -0.73233435, -0.73241423, -0.73247587, -0.73253049, -0.73259774, -0.73260887, -0.73264666, -0.73271391, -0.73275871, -0.73281895, -0.73289883, -0.73296047, -0.73302913, -0.73302623, -0.73304999, -0.73311163, -0.73312416, -0.73315773, -0.73318149, -0.7331814 , -0.73323322, -0.73330187, -0.73332002, -0.73337184, -0.73335351, -0.73338989, -0.73344872, -0.73345003, -0.73345695, -0.73345264, -0.73342448, -0.73339632, -0.7333892 , -0.7333442 , -0.73332587, -0.7332458 , -0.73323728, -0.73322736, -0.73320622, -0.7331949 , -0.73312745, -0.7330586 , -0.73306411, -0.73293633, -0.7328324 , -0.73276635, -0.73270312, -0.73252904, -0.73240406, -0.73226506, -0.73214711, -0.7320067 , -0.73183122, -0.73163609, -0.73140308, -0.73120374, -0.73091461, -0.73058197, -0.7302325 , -0.72988303, -0.72945919, -0.72895959, -0.72834634, -0.72762223, -0.72676764, -0.72574324, -0.72453505, -0.72311926, -0.72143543, -0.71945413, -0.71707295, -0.71423016, -0.71089909, -0.70701376, -0.70239039, -0.6968845 , -0.69039366, -0.68265121, -0.67319841, -0.66076033, -0.64079696, -0.60317497, -0.56293919, -0.52752295, -0.49321016, -0.45954909, -0.4262248 , -0.393312 , -0.36065093, -0.32825998, -0.29616902, -0.2643183 , -0.23270091, -0.20137202, -0.17022474, -0.1393085 , -0.10873134, -0.07845648, -0.04833679, -0.01849526, 0.01110949, 0.04044527, 0.06955692, 0.09842259, 0.12705722, 0.1554045 , 0.18350694, 0.21133123, 0.23886472, 0.26621314, 0.29328341, 0.32003758, 0.34652509, 0.37276202, 0.39875757, 0.42435198, 0.44962109, 0.47455572, 0.49911909, 0.52330545, 0.5471033 , 0.57038276, 0.59323694, 0.61546467, 0.63712229, 0.65788796, 0.67742259, 0.69509631, 0.7100183 , 0.72151845, 0.72918653, 0.73227346, 0.73275623, 0.7329682 , 0.73315772, 0.73330795, 0.73344835, 0.73347089, 0.73355377, 0.73363524, 0.733662 , 0.73373786, 0.73379408, 0.73387134, 0.73393458, 0.73396414, 0.73399511, 0.733998 , 0.73402336, 0.73400943, 0.73398848, 0.73405873, 0.73406163, 0.7340982 , 0.73413197, 0.73413909, 0.73417426, 0.7342782 , 0.73435967, 0.73440607, 0.7344665 , 0.73449326, 0.73446669, 0.73455799, 0.73470262, 0.73482057, 0.7348838 , 0.73495686, 0.73500467, 0.73504967, 0.73512413, 0.73518596, 0.73520991, 0.73524368, 0.73529289, 0.73529158, 0.73529589, 0.7353016 , 0.73534519, 0.73543509, 0.73548289, 0.73550685])
guest

回答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()

イメージ説明

【NumPy】配列の勾配 numpy.gradient

投稿2020/12/01 11:51

編集2020/12/01 13:42
meg_

総合スコア10740

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KNKR

2020/12/01 12:14

ご回答ありがとうございました!np.gradientは差分を見ているのではなく、微分の定義そのもののようなコマンドだということですね。助かりました!
meg_

2020/12/01 12:17

すみません。上記もxの間隔がデフォルト値の1の場合でした。
meg_

2020/12/01 12:27

xの差分を考慮しようと思ったのですが、良く見るとxの並びが前後している部分がいくつかありますね。 例:397.75174812, 397.69494205 ← xの後ろから3番目と2番目 そのため計算できませんでした。
KNKR

2020/12/01 12:52

ちょうど質問しようとしていたところでした(笑) やはり間隔がバラバラだと使えないですかね…。 もし、xの並びが前後しないような綺麗なデータが取れた時はどうするのがいいでしょうか。お時間ありましたらコメントお願いいたします。
KNKR

2020/12/01 17:30

追記ありがとうございました!また試行錯誤してみます!
meg_

2020/12/02 00:37

データが関数で作成されたものではなく実測値の場合はこのようなプロットになりませんか?(ばらつきの範囲とは考えられませんか?)
KNKR

2020/12/02 05:43

考えられますね。やはり実測値の微小分を用いた微分では仕方ないですよね。 測定方法などを見直してみます。対応本当にありがとうございました。
guest

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
jbpb0

総合スコア7653

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KNKR

2020/12/02 05:44

なめらかな曲線が描けました。対応本当にありがとうございました。
jbpb0

2020/12/02 06:04 編集

関数の三つ目の引数(window)を大きくするほど、平滑化が強くなり細かいデコボコが減りますが、全体の形状(左右の急激な立ち上がり・立ち下がり等)が徐々に崩れてきます そのバランスで数値を決めますので、最適な数値はデータや目的によってケースバイケースです
jbpb0

2020/12/02 14:17

二階微分の処理にバグがあったので、関数non_uniform_savgol_derのコードを差し替えました なお、(二階ではない単なる)微分には影響ありません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問