pandas,matplotlib,使用数据框索引作为轴刻度标签

8

我正在使用matplotlib的imshow()函数来显示pandas.DataFrame

我希望x轴和y轴的标签和刻度都可以从DataFrame.indexDataFrame.columns列表中绘制,但我不知道如何做到这一点。

假设data是一个pandas.DataFrame

>>> print data
<class 'pandas.core.frame.DataFrame'>
Index: 201 entries,  1901 to  2101
Data columns:
jan    201  non-null values
feb    201  non-null values
mar    201  non-null values
apr    201  non-null values
may    201  non-null values
jun    201  non-null values
jul    201  non-null values
aug    201  non-null values
sep    201  non-null values
oct    201  non-null values
nov    201  non-null values
dec    201  non-null values

当我执行以下操作时:
ax1 = fig.add_subplot(131, xticklabels=data.columns, yticklabels=data.index)
ax1.set_title("A")
ax1.tick_params(axis='both', direction='out')
im1 = ax1.imshow(data, 
                 interpolation='nearest', 
                 aspect='auto',
                 cmap=cmap )

我得到了一个在图像y轴上有漂亮间隔刻度标签的结果,但是标签显示为1901-1906而不是1901至2101。同样,x轴的刻度标签显示为二月至七月而不是一月至十二月。
如果使用代码:
ax1 = fig.add_subplot(131) # without specifying tick labels

我最终得到的轴刻度标签只是基础ndarray索引值(即0-201和0-12)。我不需要修改刻度和标签的间距或数量,只想让标签文本来自DataFrame索引和列列表。不确定是否漏掉了一些简单的东西?

提前致谢。

3个回答

9
我认为问题与指定现有刻度标签有关。默认情况下,刻度比标签少,因此只使用前几个标签。以下操作应该有效,首先设置刻度的数量。
ax1 = fig.add_subplot(131)
ax1.set_title("A")
ax1.tick_params(axis='both', direction='out')
ax1.set_xticks(range(len(data.columns)))
ax1.set_xticklabels(data.columns)
ax1.set_yticks(range(len(data.index)))
ax1.set_yticklabels(data.index)
im1 = ax1.imshow(data, interpolation='nearest', aspect='auto', cmap=cmap)

这会在y轴上每年产生一个刻度,因此您可能希望使用索引值的子集。


1
这是最通用的解决方案 - 不需要 DateTime 的 hack 等。 - FuzzyDuck

6

作为一种常用的解决方案,我发现以下方法是将Pandas datetime64索引转换为matplotlib轴标签的简单方法。

首先,通过将Pandas datetime64索引转换为Python datetime.datetime类来创建一个新系列。

new_series = your_pandas_dataframe.index.to_pydatetime()

现在您拥有了matplotlib.dates的所有功能。在绘图之前,导入matplotlib.dates作为mdates并声明以下变量:

years = mdates.YearLocator()   
months = mdates.MonthLocator()  
days = mdates.DayLocator()
hours = mdates.HourLocator(12) #if you want ticks every 12 hrs, you can pass 12 to this function
minutes = mdates.MinuteLocator() 
daysFmt = mdates.DateFormatter('%m/%d') #or whatever format you want

现在,使用new_series作为x轴来制作你的图表:
fig1 = plt.figure()
ax = fig1.add_subplot(111)
ax.plot(new_series,your_pandas_dataframe)

您可以使用上面声明的mdates函数来调整标签和刻度,使其更符合您的需求,例如:
ax.xaxis.set_major_locator(days)
ax.xaxis.set_major_formatter(daysFmt)
ax.xaxis.set_minor_locator(hours)

3

我发现最简单的方法是使用 ImageGrid。以下是代码以及绘图结果,这里还有一个IPython笔记本,它以更可读的格式呈现:

mons = ['Jan',
 'Feb',
 'Mar',
 'Apr',
 'May',
 'Jun',
 'Jul',
 'Aug',
 'Sep',
 'Oct',
 'Nov',
 'Dec']

# just get the first 5 for illustration purposes
df = DataFrame(randn(201, len(mons)), columns=mons,
               index=arange(1901, 2102))[:5]

from mpl_toolkits.axes_grid1 import ImageGrid
fig = figure(figsize=(20, 100))
grid = ImageGrid(fig, 111, nrows_ncols=(1, 1),
                 direction='row', axes_pad=0.05, add_all=True,
                 label_mode='1', share_all=False,
                 cbar_location='right', cbar_mode='single',
                 cbar_size='10%', cbar_pad=0.05)

ax = grid[0]
ax.set_title('A', fontsize=40)
ax.tick_params(axis='both', direction='out', labelsize=20)
im = ax.imshow(df.values, interpolation='nearest', vmax=df.max().max(),
               vmin=df.min().min())
ax.cax.colorbar(im)
ax.cax.tick_params(labelsize=20)
ax.set_xticks(arange(df.shape[1]))
ax.set_xticklabels(mons)
ax.set_yticks(arange(df.shape[0]))
ax.set_yticklabels(df.index)

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接