首页 > 解决方案 > Python 3.7:用不同的 x 轴值填充两条线之间的区域,这些值曲折很多

问题描述

我有一个数据集,我想将其不确定性表示为主图周围的填充区域。x轴方向的误差很大,所以我一直无法使用plt.fill_between(x, y1, y2),这需要一组通用的x轴。

我曾尝试plt.fill(np.append(x1, x2[::-1]))按照本网站其他地方的建议使用,但由于我的数据上下曲折很多,填充的区域最终看起来像节点(见附图)。

我试图将其不确定性绘制为填充区域的数据图。 使用 <code>plt.fill()</code> 会导致填充节点。

我想要完成的是点对点填充,即为每个 i 的值填充下界的第 i 个值和上界的第 i 个值之间的区域,这样主线实际数据始终在填充区域内..

我目前使用的代码附在下面。提前感谢您的建议/帮助!

import numpy as np
import matplotlib.pyplot as plt


# Generate data
data = [  # 1st set
        np.asarray([[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147],
                    [0.95655418,0.968751302,0.983557511,1,0.990592677,0.97449496,0.95440505,0.924954671,0.886996122,0.82251848,0.778125913,0.73916151,0.700254675,0.668987694,0.63055911,0.590810638,0.555342043,0.507765573,0.4616611,0.429145607,0.413109798,0.390302561,0.363457831,0.342211112,0.318108912,0.294919636,0.2604157,0.234729394,0.215631188,0.19881722,0.183199438,0.16849855,0.155955983,0.139366571,0.130774073,0.122769502,0.113845958,0.108554715,0.100988871,0.096328988,0.089256135,0.084745413,0.079921355,0.074552516,0.069711584,0.065973993,0.063518416,0.060676971,0.057921448,0.054652475,0.052496131,0.049222527,0.046675798,0.044500797,0.043952159,0.041155119,0.043656139,0.040926506,0.039692837,0.037439469,0.036360189,0.035155463,0.033663854,0.032398257,0.03094279,0.029410186,0.028667612,0.02746653,0.026438134,0.025641696,0.024370006,0.023830637,0.023306691,0.021891054,0.020939248,0.019839459,0.019218755,0.019261568,0.019029851,0.018123198,0.01710584,0.016715688,0.01618066,0.015785562,0.014618372,0.013970195,0.013450019,0.0130316,0.012526295,0.012519175,0.0111811,0.010592157,0.010524284,0.010147982,0.010100317,0.009651263,0.009243377,0.009168683,0.008427179,0.008649776,0.00849209,0.008433903,0.008057094,0.007496825,0.007536894,0.007522125,0.007019614,0.007308734,0.006747738,0.006585782,0.006723507,0.006146523,0.005883389,0.006014114,0.005708983,0.005689707,0.00532408,0.005527866,0.00545286,0.004954855,0.004833038,0.004554934,0.004251427,0.004186365,0.004252841,0.003897866,0.003731514,0.003545388,0.003436594,0.003431516,0.003253962,0.002831155,0.002969271,0.001684758,0.001340519,0.001385708,0.001303324,0.001303421,0.001044814,0.001077059,0.001093969]]),
          # 2nd set
        np.asarray([[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95],
                    [0.914033852,0.950504849,0.80004654,0.695783944,0.662746701,0.695576344,0.90154606,1,0.81140764,0.678474576,0.634939708,0.607590316,0.518639178,0.207727727,0.216432158,0.224586428,0.279720169,0.245618979,0.222696026,0.199679098,0.179142946,0.158946171,0.14188248,0.127260706,0.112782138,0.100888414,0.089853204,0.08216043,0.073372773,0.067958601,0.061487526,0.055911548,0.050893264,0.046562233,0.042915263,0.039707178,0.036378441,0.033371983,0.030817107,0.028757013,0.026475762,0.024725777,0.022679087,0.020535423,0.019044371,0.017906946,0.016977675,0.016137162,0.015026638,0.013821426,0.012863647,0.011716813,0.011141965,0.010609055,0.00977254,0.009348052,0.008344767,0.007617324,0.007495344,0.006615654,0.006292315,0.006144333,0.005258415,0.004866276,0.004712482,0.004014683,0.004069901,0.00361893,0.003229981,0.003008768,0.003020642,0.00285177,0.00227489,0.002182672,0.001804809,0.001610111,0.001768367,0.001669851,0.001623464,0.001456057,0.001114707,0.0011109,0.001091451,0.001165129,0.000900596,0.000952285,0.000960306,0.000922442,0.000836143]]),
          # 3rd set        
        np.asarray([[5,6,7,8,9,10,11,12,13,14,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],
                    [1,0.927662075,0.96202778,0.924335135,0.828600389,0.613168998,0.434280748,0.33575471,0.226712113,0.179613025,0.094097102,0.132828886,0.183557076,0.139710035,0.101280635,0.07329473,0.056400289,0.043787685,0.033451036,0.026281189,0.019311693,0.015875145,0.014837602,0.012488443,0.011285327,0.009343611,0.008602607,0.007826083,0.006956754,0.005454963,0.005808192]]),
          # 4th set
        np.asarray([[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365],
                    [0.885909672,1,0.99162113,0.872488779,0.87398788,0.805963959,0.74319068,0.726634486,0.740202316,0.730969223,0.670578511,0.624200235,0.613225969,0.575205857,0.609029515,0.597698204,0.57980882,0.576631664,0.581497131,0.593804795,0.606824276,0.640333687,0.634379114,0.656129569,0.663956949,0.634547791,0.595586735,0.581772148,0.569338853,0.555159526,0.545101106,0.525147065,0.502896746,0.497743379,0.493600401,0.49762563,0.477230369,0.482063433,0.477360682,0.467838442,0.467380429,0.47560526,0.468880058,0.487816836,0.480472169,0.467176897,0.460125843,0.448287451,0.437142557,0.42658121,0.413663556,0.408012163,0.402944298,0.395960648,0.392914203,0.385336533,0.382498637,0.380576939,0.375302121,0.372433499,0.372657596,0.371524779,0.367985585,0.366572768,0.368253803,0.371552111,0.378665281,0.384730649,0.391524758,0.393310424,0.400383444,0.412549566,0.419823185,0.429974348,0.443500171,0.467968688,0.476722667,0.480154755,0.485114033,0.49532665,0.491100296,0.487384531,0.48849776,0.495426176,0.495257257,0.481092465,0.436619122,0.408269466,0.374306761,0.373166502,0.382555796,0.378342072,0.346950265,0.317572698,0.252999696,0.153670297,0.136906858,0.128124111,0.118055812,0.11413037,0.110161997,0.10628067,0.098298601,0.093111985,0.088350851,0.08576681,0.079879986,0.074838647,0.072270659,0.068716759,0.066169679,0.065067294,0.064145231,0.061806894,0.060669599,0.059005956,0.057686128,0.05512712,0.053881379,0.052239032,0.051214915,0.050582681,0.049530671,0.048884795,0.051156767,0.049774256,0.0514431,0.05146419,0.051118524,0.050911102,0.049803011,0.049447797,0.048438409,0.048405349,0.046723778,0.046154424,0.04552512,0.044032249,0.043395595,0.043308933,0.042585152,0.041754058,0.040325688,0.039175667,0.039162313,0.037457688,0.037956389,0.037296581,0.036296388,0.035926523,0.035588571,0.034830947,0.035225701,0.034703098,0.033922258,0.033755366,0.033411962,0.032572077,0.032549764,0.032282915,0.032172298,0.031884569,0.031313459,0.031114445,0.031373301,0.031243683,0.031569485,0.030555099,0.031135214,0.031321489,0.030749573,0.029966772,0.03061446,0.030135384,0.030585367,0.029686435,0.02988313,0.029481707,0.02910797,0.029261633,0.029571263,0.029690859,0.028788667,0.028728067,0.028809428,0.029128161,0.028235243,0.02782359,0.027672193,0.027629457,0.027277172,0.027107321,0.026965431,0.026783799,0.026939647,0.026590097,0.026175666,0.026194135,0.025958189,0.025875979,0.026209379,0.02533026,0.025988519,0.025428073,0.018142192,0.018212207,0.017783734,0.017665953,0.017192459,0.016945588,0.016437243,0.016641711,0.016239232,0.016401381,0.015912438,0.016196707,0.016107538,0.015733245,0.015514499,0.015532215,0.015836562,0.015428837,0.0157516,0.014978627,0.014932577,0.014423966,0.014887073,0.014867981,0.014573822,0.014581828,0.014697673,0.014533383,0.014405806,0.014522672,0.014052074,0.014218667,0.014169407,0.014463344,0.014302986,0.013865811,0.013956405,0.014048572,0.013790196,0.014130022,0.014036684,0.014114657,0.014071971,0.013703234,0.013826223,0.013563827,0.013678588,0.013383205,0.013217588,0.013010951,0.012847964,0.013262616,0.013069786,0.013113281,0.013071785,0.012477441,0.012546062,0.012646679,0.012860151,0.012243156,0.012315449,0.012518825,0.012396436,0.012397889,0.012489189,0.012442466,0.012540196,0.012643484,0.01227506,0.012253067,0.011976709,0.012023984,0.011997722,0.012033947,0.012080226,0.012191508,0.011918882,0.011854949,0.011518262,0.011825999,0.011507567,0.011218112,0.011136758,0.010964953,0.011244613,0.011005658,0.010895433,0.011235724,0.010974862,0.010672335,0.010636289,0.010645618,0.010843378]])]

# Generate color set
color_set = ["blue",
             "red",
             "green",
             "orange"]

# Create figure to plot data in
plt.figure(figsize=(4, 3)).add_axes([0.1,
                                     0.1,
                                     0.8,
                                     0.8])
# Iterate through data and plot it
for i in range(0, len(data)):
    d = data[i]

    # Create lists
    x = d[0] * 6
    y = d[1]
    x_err = 0.1 * x
    y_err = 0.01 * y

    # Set lower and upper bounds for error region    
    x_lo = x - x_err
    x_hi = x + x_err
    y_lo = y - y_err
    y_hi = y + y_err

    # Set color
    color = color_set[i]

    # Plot lines
    plt.plot(x, y,
             linestyle="-",
             linewidth=1.0,
             marker="o",
             markersize=2,
             color=color)

    """
    PYPLOT FILL
    This method involves filling an area defined by the high and low errors in
    the x and y axes directions. However, regions of overlap appear darker in
    colour, which is not ideal

    # Generate shaded region of uncertainty
    plt.fill(np.append(x_lo, x_hi[::-1]),
             np.append(y_lo, y_hi[::-1]),
             color=color,
             linewidth=0.0,
             alpha=0.5)
    """

    """
    SHAPELY POLYGON
    This method was introduced by @William Miller on StackExchange, and makes use 
    of the "shapely" Python module. A polygon describing the region of error is 
    first defined for each point, and the polygons are then merged together and 
    the region is filled
    """

    for k in range(1, len(d)):
        # Check to see what the polygon is like
        """
        Not all the regions in this method overlap

        area = geometry.Polygon([(x_lo[k - 1], y_lo[k - 1]),
                                 (x_lo[k], y_lo[k]),
                                 (x_hi[k], y_lo[k]),
                                 (x_hi[k], y_hi[k]),
                                 (x_hi[k - 1], y_hi[k - 1]),
                                 (x_lo[k - 1], y_hi[k - 1])])
        """
        """
        # Polygon describing error around each point
        area1 = geometry.Polygon([(x_lo[k - 1], y[k - 1]),
                                  (x[k - 1], y_lo[k - 1]),
                                  (x_hi[k - 1], y[k - 1]),
                                  (x[k - 1], y_hi[k - 1])])
        area2 = geometry.Polygon([(x_lo[k], y[k]),
                                  (x[k], y_lo[k]),
                                  (x_hi[k], y[k]),
                                  (x[k], y_hi[k])])
        # Polygon bridging the two points
        area3 = geometry.Polygon([(x_lo[k - 1], y[k - 1]),
                                  (x_lo[k], y[k]),
                                  (x_hi[k], y[k]),
                                  (x_hi[k - 1], y[k - 1])])
        area4 = geometry.Polygon([(x[k - 1], y_lo[k - 1]),
                                  (x[k], y_lo[k]),
                                  (x[k], y_hi[k]),
                                  (x[k - 1], y_hi[k - 1])])
        area = cascaded_union([area1, area2, area3, area4])
        area_x, area_y = area.exterior.xy
        plt.gca().add_patch(patches.Polygon(np.stack([area_x, area_y], 1),
                                            facecolor=color,
                                            alpha=0.2))
        """

    err_shaded = []
    for k in range(1, len(d)):
        # Polygon defining error region for each point
        area1 = geometry.Polygon([(x_lo[k - 1], y[k - 1]),
                                  (x[k - 1], y_lo[k - 1]),
                                  (x_hi[k - 1], y[k - 1]),
                                  (x[k - 1], y_hi[k - 1])])
        area2 = geometry.Polygon([(x_lo[k], y[k]),
                                  (x[k], y_lo[k]),
                                  (x_hi[k], y[k]),
                                  (x[k], y_hi[k])])
        # Polygon bridging the two points
        # Bridge along x errors
        area3 = geometry.Polygon([(x_lo[k - 1], y[k - 1]),
                                  (x_lo[k], y[k]),
                                  (x_hi[k], y[k]),
                                  (x_hi[k - 1], y[k - 1])])
        # Bridge along y errors
        area4 = geometry.Polygon([(x[k - 1], y_lo[k - 1]),
                                  (x[k], y_lo[k]),
                                  (x[k], y_hi[k]),
                                  (x[k - 1], y_hi[k - 1])])
        # Merge the areas together
        area = cascaded_union([area1, area2, area3, area4])
        # Append the shaded error region for this point to the list
        err_shaded.append(area)
    err_shaded = cascaded_union(err_shaded)
    area_x, area_y = err_shaded.exterior.xy
    plt.gca().add_patch(patches.Polygon(np.stack([area_x, area_y], 1),
                                        facecolor=color,
                                        alpha=0.2))

plt.savefig(r"test_plot_err_shaded.png",
            figsize=(4, 3),
            dpi=300)
plt.close()

标签: pythonmatplotlibfill

解决方案


这更像你正在寻找的吗?

在此处输入图像描述

您可以通过将填充的多边形分解为、、和数组plt.fill()的较小部分并像这样分别填充每个段来创建它x_lox_hiy_loy_hi

from matplotlib.colors import to_rgb
color = to_rgb(color_set[i])
for k in range(1, len(x), 1):
    xe = [x_lo[k], x_lo[k-1], x_hi[k-1], x_hi[k]]
    ye = [y_lo[k], y_lo[k-1], y_hi[k-1], y_hi[k]]
    plt.fill(xe, ye, fc=(color[0], color[1], color[2], 0.3))

这实际上并不是解决此问题的最佳方法,但它可能足以满足您的目的。一种更稳健的方法是使用创建级联联合shapely.ops.cascaded_union

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import to_rgb
from matplotlib import patches
from shapely.ops import cascaded_union
from shapely import geometry

# Unchanged code omitted

for i in range(0, len(data)):
    # Unchanged code omitted
    # Set color
    color = to_rgb(color_set[i])
    color = (color[0], color[1], color[2], 0.3)

    # Plot lines
    plt.plot(x, y, linestyle="-", linewidth=1.0, marker="o", markersize=2, color=color)
    # Plot region of error
    polygons = list()
    for k in range(1, len(x), 1):
        polygons.append(geometry.Polygon([(x_lo[k], y_lo[k]), (x_lo[k-1], y_lo[k-1]), 
                                          (x_hi[k-1], y_hi[k-1]), (x_hi[k], y_hi[k])]))

    boundary = cascaded_union(polygons)
    x, y = boundary.exterior.xy
    ax.add_patch(patches.Polygon(np.stack([x, y], 1), fc=color))

plt.show()

这会给你一些看起来像这样的东西

在此处输入图像描述


推荐阅读