我正在尝试在两个相邻的时间间隔之间进行填充:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame({'Value': np.random.randint(10,size=10),
'Color': ['r','r','r','r','r','r','g','g','g','g']})
fig,ax = plt.subplots(1,1,figsize=(8,3))
ax.plot(df.Value)
ax.fill_between(df.index[df.Color == 'r'],
df.Value[df.Color == 'r'], color='r')
ax.fill_between(df.index[df.Color == 'g'],
df.Value[df.Color == 'g'], color='g')
哪个给我:
但是,我也想给索引5和6(红色)之间的间隔加上颜色。
我该怎么做?
答案 0 :(得分:2)
您不仅要填充Color
是r
的位置,还要填充颜色从红色变为绿色的位置。您可以将其公式化为条件,并在where
中使用fill_between
参数。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame({'Value': np.random.randint(10,size=10),
'Color': ['r','r','r','r','r','r','g','g','g','g']})
fig,ax = plt.subplots(1,1,figsize=(8,3))
ax.plot(df.Value)
cond = df.Color == 'r'
cond2 = cond ^ np.concatenate(([0],np.diff(cond.astype(int)) == -1))
ax.fill_between(df.index, df.Value, where=cond2, color='r')
ax.fill_between(df.index, df.Value, where=~cond, color='g')
plt.show()
虽然在这种情况下可以正常工作,但是当涉及单个间隔时,它将失败。在这种情况下,您将无法使用fill_between
。
在点之后的间隔中使曲线下方的区域着色的最一般的解决方案如下。这会根据条件创建一个顶点多边形,并以相应的颜色绘制这些多边形的集合。
在此示例中,显示了一些测试用例:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection
t1 = ['r','r','r','r','r','r','g','g','g','g']
t2 = ['r','g','r','r','g','r','g','g','r','g']
t3 = ['g','g','r','r','g','r','g','g','r','r']
t4 = ['g','r','g','g','r','g','g','g','g','r']
df = pd.DataFrame({'Value': np.random.randint(10,size=10),
'Color1': t1, "Color2": t2, 'Color3': t3, "Color4": t4})
def fill_intervals_post(x,y, color, cond, ax=None):
ax = ax or plt.gca()
cond1 = color == cond
start = np.diff(cond1.astype(int)) == 1
end = np.diff(cond1.astype(int)) == -1
inxstart = np.arange(len(color)-1)[start]+1
inxend = np.arange(len(color)-1)[end]+2
inx = np.concatenate(([0,0],np.sort(np.concatenate((inxstart,inxend)))))
xs = np.split(x, inx)[(~cond1).astype(int)[0]::2]
ys = np.split(y, inx)[(~cond1).astype(int)[0]::2]
verts = []
for xi,yi in zip(xs,ys):
xsi = np.concatenate((xi, xi[::-1]))
ysi = np.concatenate((yi, np.zeros_like(yi)))
verts.append(np.c_[xsi,ysi])
p = PolyCollection(verts, color=cond)
ax.add_collection(p)
fig,axes = plt.subplots(4,1,figsize=(8,9))
for i,ax in enumerate(axes):
ax.plot(df.index.values, df.Value.values, color="k")
ax.set_title(df["Color{}".format(i+1)].values)
fill_intervals_post(df.index.values,df.Value.values,
df["Color{}".format(i+1)].values, "r", ax=ax)
fill_intervals_post(df.index.values,df.Value.values,
df["Color{}".format(i+1)].values, "g", ax=ax)
fig.tight_layout()
plt.show()