Matplotlib:pandas MultiIndex DataFrame 的自定义代码

亚当斯图尔特

我有一个想要绘制的大熊猫 MultiIndex DataFrame一个最小的例子看起来像:

import pandas as pd

years = range(2015, 2018)
fields = range(4)
days = range(4)
bands = ['R', 'G', 'B']

index = pd.MultiIndex.from_product(
    [years, fields], names=['year', 'field'])
columns = pd.MultiIndex.from_product(
    [days, bands], names=['day', 'band'])

df = pd.DataFrame(0, index=index, columns=columns)

df.loc[(2015,), (0,)] = 1
df.loc[(2016,), (1,)] = 1
df.loc[(2017,), (2,)] = 1

如果我使用 绘制此图plt.spy,我会得到:

简单的情节

但是,刻度位置和标签不太理想。我希望刻度完全忽略 MultiIndex 的第二级。使用IndexLocatorand IndexFormatter,我可以执行以下操作:

from matplotlib.ticker import IndexFormatter, IndexLocator

import matplotlib.pyplot as plt

ax = plt.gca()
plt.spy(df)

xbase = len(bands)
xoffset = xbase / 2
xlabels = df.columns.get_level_values('day')
ax.xaxis.set_major_locator(IndexLocator(base=xbase, offset=xoffset))
ax.xaxis.set_major_formatter(IndexFormatter(xlabels))
plt.xlabel('Day')
ax.xaxis.tick_bottom()

ybase = len(fields)
yoffset = ybase / 2
ylabels = df.index.get_level_values('year')
ax.yaxis.set_major_locator(IndexLocator(base=ybase, offset=yoffset))
ax.yaxis.set_major_formatter(IndexFormatter(ylabels))
plt.ylabel('Year')

plt.show()

这正是我想要的:

在此处输入图片说明

But here's the problem. My actual DataFrame has 15 years, 4,000 fields, 365 days, and 7 bands. If I actually label every single day, the labels would be illegible. I could place a tick every 50 days, but I would like the ticks to be dynamic so that when I zoom in, the ticks become more fine-grained. Basically what I'm looking for is a custom MultiIndexLocator that combines the placement of IndexLocator with the dynamism of MaxNLocator.

Bonus: My data is really nice in the sense that there are always the same number of fields for every year and the same number of bands for every day. But what if this was not the case? I would love to contribute a generic MultiIndexLocator and MultiIndexFormatter to matplotlib that works for any MultiIndex DataFrame.

ImportanceOfBeingErnest

Matplotlib 不知道数据帧或 MultiIndex。它只是绘制您提供的数据。即,您得到的结果与绘制 numpy 数据数组相同spy(df.values)

所以我建议首先正确设置图像的范围,以便您可以使用数字代码。那么 aMaxNLocator应该可以正常工作,除非您不放大太多。

import numpy as np
import pandas as pd
from matplotlib.ticker import MaxNLocator
import matplotlib.pyplot as plt
plt.rcParams['axes.formatter.useoffset'] = False

years = range(2000, 2018)
fields = range(9) #17
days = range(120) #365
bands = ['R', 'G', 'B', 'A']

index = pd.MultiIndex.from_product(
    [years, fields], names=['year', 'field'])
columns = pd.MultiIndex.from_product(
    [days, bands], names=['day', 'band'])

data = np.random.rand(len(years)*len(fields),len(days)*len(bands))
x,y = np.meshgrid(np.arange(data.shape[1]),np.arange(data.shape[0]))
data += 2*((y//len(fields)+x//len(bands)) % 2)
df = pd.DataFrame(data, index=index, columns=columns)

############
# Plotting
############

xbase = len(bands)
xlabels = df.columns.get_level_values('day')
ybase = len(fields)
ylabels = df.index.get_level_values('year')

extent = [xlabels.min()-np.diff(np.unique(xlabels))[0]/2.,
          xlabels.max()+np.diff(np.unique(xlabels))[0]/2.,
          ylabels.min()-np.diff(np.unique(ylabels))[0]/2.,
          ylabels.max()+np.diff(np.unique(ylabels))[0]/2.,]

fig, ax = plt.subplots()

ax.imshow(df.values, extent=extent, aspect="auto")
ax.set_ylabel('Year')
ax.set_xlabel('Day')

ax.xaxis.set_major_locator(MaxNLocator(integer=True,min_n_ticks=1))
ax.yaxis.set_major_locator(MaxNLocator(integer=True,min_n_ticks=1))


plt.show()

在此处输入图片说明

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

根据列值对具有MultiIndex的pandas DataFrame进行排序

使用元组键从字典创建MultiIndex pandas DataFrame

使用Pandas MultiIndex选择多层DataFrame的行

按位置切片MultiIndex pandas DataFrame

筛选MultiIndex Pandas DataFrame

将Pandas MultiIndex DataFrame转换为嵌套字典

如何将Pandas Dataframe MultiIndex行转换为MultiIndex列?

如何通过MultiIndex和值对Pandas DataFrame进行排序?

在Pandas DataFrame中转置选定的MultiIndex级别

列计算中的Pandas MultiIndex DataFrame参考索引值

构造MultiIndex pandas DataFrame嵌套的Python字典

在创建MultiIndex列时合并Pandas DataFrame

带有MultiIndex DataFrame的fillna的Pandas SettingWithCopyWarning

具有MultiIndex列的Pandas DataFrame中的布尔索引

如何切片具有MultiIndex索引和MultiIndex列的Pandas DataFrame?

在MultiIndex DataFrame Pandas中选择子列

Pandas Dataframe Mul在Multiindex上

按MultiIndex的一级对pandas DataFrame进行排序

使用multiIndex将Pandas DataFrame转换为Series

如何从自定义 numpy dtype 创建带有 MultiIndex 的 DataFrame?

在 pandas DataFrame 的 applymap() 中使用自定义函数

Pandas Multiindex DataFrame - 按外部系列分组?

Pandas:如何将 MultiIndex DataFrame 与单个索引 DataFrame 连接起来,以及自定义排序

Pandas - 使用 MultiIndex DataFrame 的索引切入 DataFrame

更新 Pandas MultiIndex DataFrame

在 Pandas MultiIndex DataFrame 上建立索引时出现 KeyError

Pandas DataFrame 自定义 agg 函数奇怪的行为

Pandas 在 DataFrame 中对 Group By 的自定义累积计算

对 pandas MultiIndex DataFrame 中的多级列求和