【问题标题】:How do I shade the region between the two line graph如何对两个折线图之间的区域进行着色
【发布时间】:2021-05-13 09:59:30
【问题描述】:

我在对两个折线图之间的区域进行着色时遇到问题,因为它们都有不同的日期值(x 轴)。

代码如下:

plt.figure(figsize=(30,20))
fig, ax = plt.subplots(1)

plt.plot(highs['Date'], highs['Data_Value'], label = "Record High")
plt.plot(lows['Date'], lows['Data_Value'], label = "Record Low")
plt.scatter(tmin2015['Date'].tolist(), tmin2015['Data_Value'], marker='o', c='green', label="2015 record low")
x = plt.gca().xaxis
plt.xlabel("Year", fontsize=16)
plt.ylabel("Temperature in \N{DEGREE SIGN}C", fontsize=16)
plt.title("Extreme Temperature Recorded Every Year")

for item in x.get_ticklabels():
    item.set_rotation(45)
plt.legend(loc='best')

# ax.fill_between(highs['Date'],lows['Data_Value'], highs['Data_Value'])
plt.show()

【问题讨论】:

    标签: python pandas matplotlib data-science


    【解决方案1】:

    fill_between 假设您对两个系列都有共同的 x 值。如果开始值和结束值相同,则可以插入 as implemented here。但是,在您的示例中并非如此。 您可以改为创建一个路径对象并将其添加为填充补丁:

    import matplotlib.pyplot as plt
    import pandas as pd
    from matplotlib.path import Path
    from matplotlib.patches import PathPatch
    
    fig, ax = plt.subplots(figsize=(15, 10))
    
    #test data generation
    highs = pd.DataFrame({'Date': [1, 2, 4, 5], 'Data_Value': [17, 21, 18, 19]})
    lows = pd.DataFrame({'Date': [0, 2, 3, 4], 'Data_Value': [1, 3, 2, 3]})
    
    #path object added as patch
    p = Path(list(zip(lows['Date'], lows['Data_Value']))[::-1] + list(zip(highs['Date'], highs['Data_Value'])))
    patch = PathPatch(p, facecolor="orange", lw=0, alpha=0.2, zorder=-1)
    ax.add_patch(patch)
    
    #line graphs plotted on top of the patch
    ax.plot(highs['Date'], highs['Data_Value'], label = "Record High", lw=2)
    ax.plot(lows['Date'], lows['Data_Value'], label = "Record Low", lw=2)
    
    ax.set_xlabel("Year", fontsize=16)
    ax.set_ylabel("Temperature in \N{DEGREE SIGN}C", fontsize=16)
    ax.set_title("Extreme Temperature Recorded Every Year")
    
    ax.legend(loc='best')
    
    plt.show()
    

    示例输出:

    【讨论】:

    • TypeError: float() 参数必须是字符串或数字,而不是“时间戳”。我在声明“p”时遇到了这个错误
    • 如果问题没有提供minimal, reproducible example,就会发生这种情况。
    【解决方案2】:

    类似于@MrT提到的“插值法”:

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    df_high = pd.DataFrame({'Date':pd.date_range('2020-01-01',  periods=100, freq='3D'),
                           'data_value':400+np.random.randint(0,20, 100)})
    
    df_low = pd.DataFrame({'Date':pd.date_range('2020-03-03',  periods=100, freq='3D'),
                           'data_value':-200+np.random.randint(0,20, 100)})
    
    plt.figure(figsize=(30,20))
    fig, ax = plt.subplots(1)
    
    plt.plot(df_high['Date'], df_high['data_value'], label = "Record High")
    plt.plot(df_low['Date'], df_low['data_value'], label = "Record Low")
    # plt.scatter(tmin2015['Date'].tolist(), tmin2015['Data_Value'], marker='o', c='green', label="2015 record low")
    x = plt.gca().xaxis
    plt.xlabel("Year", fontsize=16)
    plt.ylabel("Temperature in \N{DEGREE SIGN}C", fontsize=16)
    plt.title("Extreme Temperature Recorded Every Year")
    
    for item in x.get_ticklabels():
        item.set_rotation(45)
    plt.legend(loc='best')
    
    min_x = max(df_high['Date'].min(), df_low['Date'].min())
    max_x = min(df_high['Date'].max(), df_low['Date'].max())
    xrange = df_low.set_index('Date').index.union(df_high.set_index('Date').index)
    lows = df_low.set_index('Date').reindex(xrange).interpolate().loc[min_x:max_x, 'data_value']
    highs = df_high.set_index('Date').reindex(xrange).interpolate().loc[min_x:max_x, 'data_value']
    ax.fill_between(lows.index, lows, highs, alpha=.4)
    

    输出:

    【讨论】:

    • 啊,好点子。我不认为这可能是填充曲线之间区域的预期输出。
    • 如果这个答案解决了你的问题,你should accept it。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多