Python:在曲线和轴之间填充颜色&区域化 [英] Python: Filling colors between curves and axes & to regionalize the areas

查看:56
本文介绍了Python:在曲线和轴之间填充颜色&区域化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在excel工作表上有两条曲线的一组x,y值.使用 xlrd 模块,我能够将它们绘制如下:

I have a set of x,y values for two curves on excel sheets. Using xlrd module, I have been able to plot them as below:

问题:

  1. 如何用不同的填充颜色为三个区域着色?曾尝试使用 fill_between 但由于不知道如何与 x 和 y 轴关联而未成功.心目中的结局如下图所示.
  1. How do I shade the three areas with different fill colors? Had tried with fill_between but been unsuccessful due to not knowing how to associate with the x and y axes. The end in mind is as diagram below.

这是我的代码:


import xlrd
import numpy as np 
import matplotlib.pyplot as plt

workbook = xlrd.open_workbook('data.xls')

sheet = workbook.sheet_by_name('p1')
rowcount = sheet.nrows 
colcount = sheet.ncols 

result_data_p1 =[]
for row in range(1, rowcount):
    row_data = []
    for column in range(0, colcount):
        data = sheet.cell_value(row, column)
        row_data.append(data)
    #print(row_data)
    result_data_p1.append(row_data)

sheet = workbook.sheet_by_name('p2')
rowcount = sheet.nrows 
colcount = sheet.ncols 

result_data_p2 =[]
for row in range(1, rowcount):
    row_data = []
    for column in range(0, colcount):
        data = sheet.cell_value(row, column)
        row_data.append(data)
    result_data_p2.append(row_data)

x1 = []
y1 = []
for i,k in result_data_p1:
    cx1,cy1 = i,k
    x1.append(cx1)
    y1.append(cy1)

x2 = []
y2 = []
for m,n in result_data_p2:
    cx2,cy2 = m,n
    x2.append(cx2)
    y2.append(cy2)

plt.subplot(1,1,1)
plt.yscale('log')
plt.plot(x1, y1, label = "Warm", color = 'red')
plt.plot(x2, y2, label = "Blue", color = 'blue')
plt.xlabel('Color Temperature (K)')
plt.ylabel('Illuminance (lm)')
plt.title('Kruithof Curve')
plt.legend()
plt.xlim(xmin=2000,xmax=7000)
plt.ylim(ymin=10,ymax=50000)
plt.show()

请指导或引导其他参考文献,如果有的话.

Please guide or lead to other references, if any.

谢谢.

推荐答案

这里是一种重新创建曲线和渐变的方法.使用对数刻度绘制背景非常复杂.因此,背景是在线性空间中创建的,并放置在单独的y轴上.如果在双轴上绘制背景,则使背景出现在其余图的后面时会遇到一些问题.因此,背景绘制在主轴上,绘图在第二个轴上.之后,第二个 y 轴再次放置在左侧.

Here is a way to recreate the curves and the gradients. It resulted very complicated to draw the background using the logscale. Therefore, the background is created in linear space and put on a separate y-axis. There were some problems getting the background behind the rest of the plot if it were drawn on the twin axis. Therefore, the background is drawn on the main axis, and the plot on the second axis. Afterwards, that second y-axis is placed again at the left.

为了绘制曲线,使用六个点对样条进行插值.由于使用普通坐标插值没有给出可接受的结果,所有内容都在对数空间中插值.

To draw the curves, a spline is interpolated using six points. As the interpolation didn't give acceptable results using the plain coordinates, everything was interpolated in logspace.

背景是逐列创建的,检查每个 x 位置的两条曲线的位置.红色曲线是人为延伸的,具有一致的面积.

The background is created column by column, checking where the two curves are for each x position. The red curve is extended artificially to have a consistent area.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from scipy import interpolate

xmin, xmax = 2000, 7000
ymin, ymax = 10, 50000
# a grid of 6 x,y coordinates for both curves
x_grid = np.array([2000, 3000, 4000, 5000, 6000, 7000])
y_blue_grid = np.array([15, 100, 200, 300, 400, 500])
y_red_grid = np.array([20, 400, 10000, 500000, 500000, 500000])

# create interpolating curves in logspace
tck_red = interpolate.splrep(x_grid, np.log(y_red_grid), s=0)
tck_blue = interpolate.splrep(x_grid, np.log(y_blue_grid), s=0)
x = np.linspace(xmin, xmax)
yr = np.exp(interpolate.splev(x, tck_red, der=0))
yb = np.exp(interpolate.splev(x, tck_blue, der=0))

# create the background image; it is created fully in logspace
# the background (z) is zero between the curves, negative in the blue zone and positive in the red zone
# the values are close to zero near the curves, gradually increasing when they are further
xbg = np.linspace(xmin, xmax, 50)
ybg = np.linspace(np.log(ymin), np.log(ymax), 50)
z = np.zeros((len(ybg), len(xbg)), dtype=float)
for i, xi in enumerate(xbg):
    yi_r = interpolate.splev(xi, tck_red, der=0)
    yi_b = interpolate.splev(xi, tck_blue, der=0)
    for j, yj in enumerate(ybg):
        if yi_b >= yj:
            z[j][i] = (yj - yi_b)
        elif yi_r <= yj:
            z[j][i] = (yj - yi_r)

fig, ax2 = plt.subplots(figsize=(8, 8))

# draw the background image, set vmax and vmin to get the desired range of colors;
# vmin should be -vmax to get the white at zero
ax2.imshow(z, origin='lower', extent=[xmin, xmax, np.log(ymin), np.log(ymax)], aspect='auto', cmap='bwr', vmin=-12, vmax=12, interpolation='bilinear', zorder=-2)
ax2.set_ylim(ymin=np.log(ymin), ymax=np.log(ymax)) # the image fills the complete background
ax2.set_yticks([]) # remove the y ticks of the background image, they are confusing

ax = ax2.twinx()  # draw the main plot using the twin y-axis
ax.set_yscale('log')
ax.plot(x, yr, label="Warm", color='crimson')
ax.plot(x, yb, label="Blue", color='dodgerblue')
ax2.set_xlabel('Color Temperature')
ax.set_ylabel('Illuminance (lm)')
ax.set_title('Kruithof Curve')
ax.legend()
ax.set_xlim(xmin=xmin, xmax=xmax)
ax.set_ylim(ymin=ymin, ymax=ymax)
ax.grid(True, which='major', axis='y')
ax.grid(True, which='minor', axis='y', ls=':')
ax.yaxis.tick_left() # switch the twin axis to the left
ax.yaxis.set_label_position('left')
ax2.grid(True, which='major', axis='x')
ax2.xaxis.set_major_formatter(mticker.StrMethodFormatter('{x:.0f} K')) # show x-axis in Kelvin
ax.text(5000, 2000, 'Pleasing', fontsize=16)
ax.text(5000, 20, 'Appears bluish', fontsize=16)
ax.text(2300, 15000, 'Appears reddish', fontsize=16)
plt.show()

这篇关于Python:在曲线和轴之间填充颜色&amp;区域化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆