Python 填充间隔不为相邻间隔着色

Python 填充间隔不为相邻间隔着色,python,pandas,matplotlib,Python,Pandas,Matplotlib,我试图在两个相邻间隔之间填充: 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,figs

我试图在两个相邻间隔之间填充:

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之间的间隔涂上颜色(红色)


我该怎么做?

您不仅要填充
颜色
r
的位置,还要填充颜色从红色变为绿色的位置。您可以将其表述为一个条件,并使用
where
参数来
fill\u-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\u

在点之后的间隔内,为曲线下方区域着色的最通用解决方案如下所示。这将基于条件创建顶点多边形,并以相应的颜色绘制这些多边形的集合

在此示例中,显示了两个测试用例:

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

您不仅要填充
颜色
r
的位置,还要填充颜色从红色变为绿色的位置。您可以将其表述为一个条件,并使用
where
参数来
fill\u-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\u

在点之后的间隔内,为曲线下方区域着色的最通用解决方案如下所示。这将基于条件创建顶点多边形,并以相应的颜色绘制这些多边形的集合

在此示例中,显示了两个测试用例:

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

我不明白,在这种情况下,“颜色”应该是什么意思。你有九个间隔需要填充,但是“颜色”有十个值。假设我们有一个时间序列,有一些因变量,还有一个外生变量,比如代码。我想通过用颜色填充间隔来显示一个代码(红色/绿色代码)在一定的间隔内处于活动状态。因此颜色[I]定义了点[I]和点[I+1]之间的间隔[I]中的颜色,最后一个颜色值是不相关的?是的,我想这就是我的意思,我不明白,在这个上下文中“颜色”应该是什么意思。你有九个间隔需要填充,但是“颜色”有十个值。假设我们有一个时间序列,有一些因变量,还有一个外生变量,比如代码。我想通过用颜色填充间隔来显示一个代码(红色/绿色代码)在一定的间隔内处于活动状态。因此颜色[I]定义了点[I]和点[I+1]之间的间隔[I]中的颜色,最后一个颜色值是不相关的?是的,我想这就是我的意思,如果“颜色”是
['r','g','r','g','r','r','r','g']
?@T先生,这当然取决于你提到的那种情况下的预期结果。颜色是为点而不是间隔定义的;但是,是的,在这种情况下,需要一个不同的条件。@T先生问题是,在最一般的情况下,在两者之间填充是不起作用的。我相应地更新了答案。是的,这个问题看起来很小,但不是因为fill_between的恼人行为。如果“Color”是
['r','g','r','g','r','g','r','r','g']
?@Mr。颜色是为点而不是间隔定义的;但是,是的,在这种情况下,需要一个不同的条件。@T先生问题是,在最一般的情况下,在两者之间填充是不起作用的。我相应地更新了答案。是的,这个问题看起来微不足道,但不是因为fill_between的恼人行为。