【问题标题】:Scatter plot with colorbar and datetime axis ticks带有颜色条和日期时间轴刻度的散点图
【发布时间】:2018-04-24 08:41:37
【问题描述】:

我迷失在 matplotlib 中使用的不同方法中。

我想创建一个颜色编码的散点图,旁边有一个颜色条,x 轴上有一个日期时间。

但根据我定义ax 的方式,我会遇到不同的错误。 以下是我的代码的核心:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.cm as cm
import matplotlib.dates as mdates

#.....loading files etc.

norm = mcolors.Normalize(vmin=0,vmax=1000)
timerange = pd.date_range(start='2015-01-01', end='2016-01-01', freq='30D')

### PLOTTING 
fig = plt.figure(figsize=(6.,5))
ax = fig.add_subplot(111)

for Af in Afiles:
    for index, row in Af.iterrows():
        time = pd.to_datetime(row['date'], format="%Y-%m-%d")
        plt.scatter(time, row['A'], c=row['z'], norm=norm, cmap=colormap,edgecolor='k', lw=0.8, s=80)

plt.xticks(timerange, rotation=90)
ax.xaxis.set_major_formatter(mdates.DateFormatter("%d/%m/%Y"))
plt.xlabel('Time', fontsize=11, color='k')

clb = fig.colorbar(ax)       
clb.ax.set_title('Value', y=-0.125, fontsize=11)
clb.ax.invert_yaxis()

fig.tight_layout()

这会产生AttributeError: 'AxesSubplot' object has no attribute 'autoscale_None'

但是如果我将我的ax 指定为散点图,以便我可以让我的颜色编码正常工作,那么我就会遇到轴格式化程序的问题。 改写ax = plt.scatter 会生成AttributeError: 'PathCollection' object has no attribute 'xaxis'

我怎样才能同时拥有颜色条和格式化的轴刻度?

【问题讨论】:

    标签: python pandas datetime matplotlib colorbar


    【解决方案1】:

    不要称分散器为ax。 (这会覆盖现有的轴 ax。)
    颜色条需要 ScalarMappable 作为第一个参数(例如散点图)。由于散点图都是归一化的,你可以从循环中使用它,

    norm = plt.Normalize(...)
    for bla in blubb:
        scatter = plt.scatter(..., norm=norm) 
    

    那么,

    clb = fig.colorbar(scatter)
    

    其余的应该保持不变。

    【讨论】:

    • 当然!傻我,谢谢。这很尴尬。
    【解决方案2】:

    基本思想是您需要为颜色条添加一个额外的轴。

    很难知道这是否完全匹配,因为您没有提供带有数据的工作示例。但这至少可以作为一个模板。

    首先,一些示例数据:

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.colors as mcolors
    import matplotlib.cm as cm
    import matplotlib.dates as mdates
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    
    vmin = 0
    vmax = 1000
    timerange = pd.date_range(start='2015-01-01', end='2016-01-01', freq='30D')
    N = len(timerange)
    
    data = np.random.randint(vmin, vmax, size=N)
    # z contains the colorbar values for each point
    cmap = plt.get_cmap('Reds')
    z = [cmap((x-vmin)/(vmax-vmin))[:3] for x in data]
    df = pd.DataFrame({"value":data, "datetime":timerange, "z":z})
    

    现在剧情:

    fig = plt.figure(figsize=(6.,5))
    ax = fig.add_subplot(111)
    
    plt.scatter(x=df.datetime.values, y=df.value.values, c=df.z)
    
    ax.set_xticklabels(timerange, rotation=90)
    ax.xaxis.set_major_formatter(mdates.DateFormatter("%d/%m/%Y"))
    ax.set_xlabel('Time')
    

    现在添加颜色条:

    norm = mcolors.Normalize(vmin=vmin,vmax=vmax)
    m = cm.ScalarMappable(cmap='Reds', norm=norm)
    m.set_array([(x-vmin)/(vmax-vmin) for x in df.value.values])
    
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", size="5%", pad=0.1)
    clb = plt.colorbar(m, cax=cax)   
    

    【讨论】:

    • 对不起,为了澄清,这对我的循环有何作用?当我没有单个数据框但有很多时,如何设置可映射的标量?对于具有许多不同值范围的许多数据框,我需要一个通用颜色条(通用配色方案)。请注意,只要我保留数字 x 轴,我的颜色条代码(设置 ax = plt.scatter 时)就可以完美运行。当我开始使用轴格式时,问题出现了。
    • 如果您需要一个通用的颜色条,那么就颜色条而言,您没有很多不同的范围,您将只有一个。选择完整数据集的最小值和最大值以设置可映射。循环可以保持不变,我只是为一个数据帧制作了示例数据来给出一个工作示例。
    • 话虽如此,ImportanceOfBeingErnest 的答案看起来更简单,我将首先承认我对 Matplotlib 没有很好的优雅感。试试他的方法!
    猜你喜欢
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    相关资源
    最近更新 更多