Plotting shaded uncertainty region in line plot in matplotlib when data has NaNs

前端 未结 2 1001
北荒
北荒 2020-12-08 22:57

I would like a plot which looks like this:

I am trying to do this with matplotlib:

fig, ax = plt.subplots()

with sns.axes_style(\"darkgrid\"):
             


        
相关标签:
2条回答
  • 2020-12-08 23:07

    Ok. So one of the problem was that the dtype of my data was object and not float and this caused fill_between to fail when it looked to see if the numbers were finite. I finally managed to do it by (a) converting to float and then (b) to solve the problem of the matching colours for uncertainty and line, to use a colour palette. So I have:

    import seaborn as sns
    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    fig, ax = plt.subplots()
    clrs = sns.color_palette("husl", 5)
    with sns.axes_style("darkgrid"):
        epochs = list(range(101))
        for i in range(5):
            meanst = np.array(means.ix[i].values[3:-1], dtype=np.float64)
            sdt = np.array(stds.ix[i].values[3:-1], dtype=np.float64)
            ax.plot(epochs, meanst, label=means.ix[i]["label"], c=clrs[i])
            ax.fill_between(epochs, meanst-sdt, meanst+sdt ,alpha=0.3, facecolor=clrs[i])
        ax.legend()
        ax.set_yscale('log')
    

    which gave me the following result:

    0 讨论(0)
  • 2020-12-08 23:12

    You could simply drop the NaNs from your means DataFrame and plot that resulting dataframe instead?

    In the example below, I tried to get close to your structure, I have a means DataFrame with some NaN sprinkled around. I suppose the stds DataFrame probably has NaN at the same locations, but in this case it doesn't really matter, I drop the NaN from means to get temp_means and I use the indices left in temp_means to extract the std values from stds.

    The plots show the results before (top) and after (bottom) dropping the NaNs

    x = np.linspace(0, 30, 100)
    y = np.sin(x/6*np.pi)
    error = 0.2
    
    means = pd.DataFrame(np.array([x,y]).T,columns=['time','mean'])
    stds = pd.DataFrame(np.zeros(y.shape)+error)
    
    #sprinkle some NaN in the mean
    sprinkles = means.sample(10).index
    means.loc[sprinkles] = np.NaN
    
    
    fig, axs = plt.subplots(2,1)
    
    axs[0].plot(means.ix[:,0], means.ix[:,1])
    axs[0].fill_between(means.ix[:,0], means.ix[:,1]-stds.ix[:,0], means.ix[:,1]+stds.ix[:,0])
    
    temp_means = means.dropna()
    
    axs[1].plot(temp_means.ix[:,0], temp_means.ix[:,1])
    axs[1].fill_between(temp_means.ix[:,0], temp_means.ix[:,1]-stds.loc[temp_means.index,0], temp_means.ix[:,1]+stds.loc[temp_means.index,0])
    
    
    plt.show()
    

    0 讨论(0)
提交回复
热议问题