

現在、fill_betweenのなかでwhereを使おうと思ったのですがx座標もデータ数も違うので、できませんでした。  
(x1, z1)＝15点  
(x2, z2)＝3031点  
以下がプログラムです。

[code]

    f1 = np.loadtxt(filepath1)
    f2 = np.loadtxt(filepath2)
    
    x1, z1 = f1[:, 0], f1[:, 1]
    x2, z2 = f2[:, 0], f2[:, 1]
    
    ##
    plt.xlabel('X') # x軸のラベル
    plt.ylabel('Z') # y軸のラベル
    plt.plot(x1, z1, color="Black", alpha=0.8, linewidth=4.0, label="data1")
    plt.plot(x2, z2, color="White", alpha=0.8, linewidth=4.0, label="data2")
    ##
    plt.legend()
    plt.fill_between(x1, z1, z2, where=z2>=z1, facecolor='green', interpolate=True)
    plt.fill_between(x1, z1, z2, where=z2<=z1, facecolor='red',   interpolate=True)
    
    # その他，描画用オプション
    plt.xticks(fontsize=10)
    plt.yticks(fontsize=10) 
    plt.ylim([-21.62, -21.46])
    plt.grid(True) #グラフの枠を作成
    plt.savefig("cm.png")
    plt.show()
    
[/code]

これで以下のような図が表示されます。  
[![画像の説明をここに入力](https://i.stack.imgur.com/6VAK0.png)](https://i.stack.imgur.com/6VAK0.png)

[code]

    Traceback (most recent call last):
    
      File "<ipython-input-2-883f16ec992c>", line 1, in <module>
        runfile('C:/Users/Administartor/Desktop/タイトル無し0.py', wdir='C:/Users/Administartor/Desktop')
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
        execfile(filename, namespace)
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
        exec(compile(f.read(), filename, 'exec'), namespace)
    
      File "C:/Users/Administartor/Desktop/タイトル無し0.py", line 46, in <module>
        plt.fill_between(x1, z1, z2, where=z2>=z1, facecolor='green', interpolate=True)
    
    ValueError: operands could not be broadcast together with shapes (3031,) (15,) 
    
[/code]

私の考えとしてはf１はただ単に点と点を繋いでいるだけなので、f2に合わせた座標が取得できればすべて解決すると思うのですが、描いたグラフから座標を抽出する方法がわからず質問することにしました。  
・描いたグラフから座標（x1=x2）の(x1,z1)を抽出する方法  
こういったことは可能でしょうか？

@kunifさんのコード

[code]

    f1 = np.loadtxt(filepath1)
    f2 = np.loadtxt(filepath2)
    
    xw, zw = f1[:, 0], f1[:, 1] # x1, z1 を作業用配列に変える
    x2, z2 = f2[:, 0], f2[:, 1]
    z1 = np.array([])           # 空の z1 を作成しておく
    for x in x2:
        idx = np.where(xw == x) # 同じ X軸 値を探して
        z1 = np.append(z1, zw[idx[0]]) # z1 に追加
    ##
    plt.xlabel('X') # x軸のラベル
    plt.ylabel('Z') # y軸のラベル
    plt.plot(x2, z1, color="Black", alpha=0.8, linewidth=4.0, label="data1")
    plt.plot(x2, z2, color="White", alpha=0.8, linewidth=4.0, label="data2")
    ##
    plt.legend()
    plt.fill_between(x2, z1, z2, where=z2>=z1, facecolor='green', interpolate=True)
    plt.fill_between(x2, z1, z2, where=z2<=z1, facecolor='red',   interpolate=True)
    
    # その他，描画用オプション
    plt.xticks(fontsize=10)
    plt.yticks(fontsize=10) 
    plt.ylim([-21.62, -21.46])
    plt.grid(True) #グラフの枠を作成
    plt.savefig("cm.png")
    plt.show()
    fig = plt.figure()
    
[/code]

エラー

[code]

    Traceback (most recent call last):
    
      File "<ipython-input-19-340b5a582673>", line 1, in <module>
        runfile('C:/Users/Administartor/Desktop/t.py', wdir='C:/Users/Administartor/Desktop')
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
        execfile(filename, namespace)
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
        exec(compile(f.read(), filename, 'exec'), namespace)
    
      File "C:/Users/Administartor/Desktop/t.py", line 45, in <module>
        plt.plot(x2, z1, color="Black", alpha=0.8, linewidth=4.0, label="data1")
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\matplotlib\pyplot.py", line 3261, in plot
        ret = ax.plot(*args, **kwargs)
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\matplotlib\__init__.py", line 1717, in inner
        return func(ax, *args, **kwargs)
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py", line 1372, in plot
        for line in self._get_lines(*args, **kwargs):
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 404, in _grab_next_args
        for seg in self._plot_args(this, kwargs):
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 384, in _plot_args
        x, y = self._xy_from_xy(x, y)
    
      File "C:\Users\Administartor\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 243, in _xy_from_xy
        "have shapes {} and {}".format(x.shape, y.shape))
    
    ValueError: x and y must have same first dimension, but have shapes (4,) and (2,)
    
[/code]


CC BY-SA 4.0
2019-11-13T06:41:16.680
60473
2023-09-14T06:04:25.610
2019-11-13T08:47:04.627
36532
36532
question
python python3 numpy matplotlib
グラフから座標を得る方法について


**質問のデータ数の大小を誤解していました**

x1z1が3031点, x2z2が15点だと誤解していました。逆ですね。

**そうすると、「そもそも何を導き出したいか」と、プログラムが合っていない可能性があります。**

x1z1のデータが周期的に規則正しくずっと続くのが模範的な状態で、x2z2は実測値で、実際の物の動作なのでブレが生じるという感じでしょうか。

x1z1と同じ1回の周期が、x2z2のデータの何処から始まるかというのが分かっていて、さらにx1z1とx2z2の同一期間のデータ数が同じであるという前提が成立している必要がありそうです。

x1z1の15点と、x2z2の3031点から引き出した15点を比べるのではなく、15点を繰り返して3000点くらいまで拡張し、開始点やデータ数を合わせてから比較するといった手法を取るのではないでしょうか？  
実態は判っていませんが、FFT解析とか、オシロスコープの動作をプログラムでシミュレートしたり、オシロスコープの自動調節機能みたいなものの雛形を考えたりしている感じかもしれません。

このプログラムの1行1行の良し悪しを検討したり質問したりするのではなく、そうした目的とデータの性質を基にした見直しが必要と思われます。

* * *

**以下は誤解していた時の回答です**  
グラフから座標を抜き取る必要は無く、前のコメントでデータの少ない方に数を合わせるのは簡単と言った方法そのものですが、こんな風になります。

[code]

    xw, zw = f1[:, 0], f1[:, 1] # x1, z1 を作業用配列に変える
    x2, z2 = f2[:, 0], f2[:, 1]
    z1 = np.array([])           # 空の z1 を作成しておく
    for x in x2:
        idx = np.where(xw == x) # 同じ X軸 値を探して
        z1 = np.append(z1, zw[idx[0]]) # z1 に追加
    
[/code]

これで`z1`と対になる`x1`は`x2`と同じになるので、それ以後の`x1`を指定するところに`x2`を指定すれば良いでしょう。  
敢えて独立した`x1`を作りたいならば、`x1 = x2.copy()`で出来ます。

* * *

何か環境にでも差があるのでしょうか？ こちらは以下になります。

Windows10 64bit  
Python 3.7.5  
pandas 0.25.3  
numpy 1.17.4

前の質問のデータを使って、「一部回転B」を以下まで削って出した結果でもちゃんとグラフになります。  
ちなみに`for`のループの直後に`##`があるのはエラーになったので空行を入れました。

[code]

    17.0484 -21.5070
    17.2787 -21.4740
    17.6784 -21.6570
    17.9087 -21.4740
    
[/code]

結果のグラフは以下になります。  
[![fill_betweenグラフ](https://i.stack.imgur.com/arYUZ.png)](https://i.stack.imgur.com/arYUZ.png)


CC BY-SA 4.0
2019-11-13T07:14:02.663
60476
2019-11-13T11:18:29.500
2019-11-13T11:18:29.500
26370
26370
60473
answer


まず，グラフから座標を得る方法については不可能なのではと思います．  
自分はmatplotlibの機能を全て把握しているわけではありませんが，あくまでグラフ描画ツールという性質上そのようなAPIはないと考えるのが自然です（必ずしもx座標とy座標が一対一対応するわけでもありませんし，何を返せばよいか定義しづらいというのもあると思います）．

ということで，できることとして大きく2つが考えられると思います．

まずは，自分で計算する．点と点を結んでいるだけなので，近い2点から直線の式を計算して，x2を代入して求めるということですね．面倒ですが，一応可能です．

次に，matplotlib以外の描画ソフトを使うという手です．例えばplotlyというライブラリがあります．  
<https://plot.ly/python/filled-area-plots/> のInterior Filling for Area
Chartのコードを少し書き換えて，

[code]

    import plotly.graph_objects as go
    
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=[1, 2, 3, 4], y=[3, 4, 8, 3],
        fill=None,
        mode='lines',
        line_color='indigo',
        ))
    fig.add_trace(go.Scatter(
        x=[1, 3, 4],
        y=[1, 2, 6],
        fill='tonexty', # fill area between trace0 and trace1
        mode='lines', line_color='indigo'))
    
    fig.show()
    
[/code]

としたら，以下のようなグラフが描画されたので，xが揃っていなくてもよしなにしてくれそうです．  
Pythonはグラフ描画ソフトはいくつもあるので，他にもそういった機能を持つものがあるかもしれません．

[![画像の説明をここに入力](https://i.stack.imgur.com/K5X2o.png)](https://i.stack.imgur.com/K5X2o.png)


CC BY-SA 4.0
2019-11-16T16:07:22.167
60595
2019-11-16T16:07:22.167
36544
60473
answer


点の少ない方のデータを線形補間することによってデータ数を揃えれば、`fill_between`で間の領域を塗りつぶすことができます。

[code]

    import matplotlib.pyplot as plt
    import numpy as np
    
    # data1: 15点の適当なデータ
    x1 = np.linspace(2, 8, 15)
    z1 = np.sin(x1)
    
    # data2: 3031点の適当なデータ
    x2 = np.linspace(0, 10, 3031)
    z2 = np.cos(x2)
    
    plt.plot(x1, z1, color="black")
    plt.plot(x2, z2, color="blue")
    
    # data1 をもとに、 x2 と対にして使えるデータを線形補間で作成
    z1_interp = np.interp(x2, x1, z1)
    
    # 実際に塗るのは、data1とdata2、両方のデータがある x の領域のみとする
    fill_xmin = max(x1[0], x2[0])
    fill_xmax = min(x1[-1], x2[-1])
    fill_range = np.logical_and(fill_xmin <= x2, x2 <= fill_xmax)
    
    plt.fill_between(x2, z1_interp, z2, where=np.logical_and(z2 >= z1_interp, fill_range), facecolor='green', interpolate=True)
    plt.fill_between(x2, z1_interp, z2, where=np.logical_and(z2 <= z1_interp, fill_range), facecolor='red', interpolate=True)
    
[/code]

[![画像の説明をここに入力](https://i.stack.imgur.com/p7Irn.png)](https://i.stack.imgur.com/p7Irn.png)


CC BY-SA 4.0
2020-11-09T13:02:42.577
71826
2020-11-09T13:02:42.577
36010
60473
answer