在pandas/matplotlib中设置xlim,其中索引为字符串

3
我有一个使用字符串作为索引的pandas dataframe。当我的数据框索引是对象类型时,我如何设置x轴的xlim?我尝试在末尾添加两年,在开头添加一年,其中所有数据集都是np.nan,但这并没有起作用。
以下是数据框: Dataframe 索引的数据类型是object。
df.index
Out[52]: Index(['2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012'], dtype='object')

这是一个图表:

Matplotlib Plot

我希望在x轴上有一些额外的空间,以便更好地显示第一年和最后一年的值。我该怎么做?

编辑

这是一个使用对象而不是日期对象作为索引的最小示例:

IPython笔记本


另外,需要明确的是,您不是在对字符串进行绘图,而是在对位置数组进行绘图。 pandas 只是过于聪明,重新标记了您的刻度标记。 - tacaswell
这是在我的ax对象上使用set_xlim时的效果http://postimg.org/image/4rnex5u0z/d0936fee/。正如您所看到的,我得到了想要的效果,但底部的标签出现了问题。 - Christian Rapp
啊,对了,因为 pandas 正在使用 FixedFormatter,所以当您更改 xlimit 时,它会更改刻度线的位置/数量,但 FixedFormatter 的工作方式是第一个刻度线获取第一个字符串,第二个获取第二个,以此类推。 - tacaswell
@tcaswell 添加了一个最小示例。请还要查看我在 CT Zhu 的答案中的评论。使用定位器删除了 x 轴上的所有标签。 - Christian Rapp
最好直接将示例代码放在问题中,链接会失效。 - tacaswell
显示剩余7条评论
2个回答

5

使用set_xlim+1表示向右移动一单位,-1表示相反。在以下示例中,我将绘图每侧扩展0.5个月:

df=pd.DataFrame({'A': range(10), 'B': range(1, 11), 'C': range(2,12)})
df.index=pd.date_range('2001/01/01', periods=10, freq='M')
ax=df.plot(kind='line')
ax.set_xlim(np.array([-0.5, 0.5])+ax.get_xlim())

enter image description here

编辑,使得在pandas中每年都有xticklabel而不是默认的每两年一个:

ax=df.plot(kind='line', xticks=df.index)
ax.set_xticklabels(df.index.map(lambda x: datetime.datetime.strftime(x, '%Y')))

enter image description here


1
这可能是另一个使用“边距”会很有用的情况。 - tacaswell
@ChristianRapp 不,将你的索引设置为 Date 对象可能是更好的解决方案。 - tacaswell
@tcaswell,在版本 1.3.1 中,ax.margins(x=0.1, y=0.1) 触发了 ValueError: more than two arguments were supplied。在 1835 和 1837 行的源代码中,不应该是 if len(args) == 2:elif len(args) == 3: 吗? - CT Zhu
请参考 https://dev59.com/f4Dba4cB1Zd3GeqPK_bd#24416670 了解如何控制日期刻度。 - tacaswell
我所指的“this”是关于“margins”的参数。 - tacaswell
显示剩余8条评论

2
from __future__ import print_function
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

df = pd.DataFrame({'Foo': pd.Series([2,3,4], index=['2002', '2003', '2004'])})
fig, ax = plt.subplots()

df.plot(ax=ax)

这将帮助您理解情节。要查看如何处理x轴刻度,请查看:

# note this is an AutoLocator
print(ax.xaxis.get_major_locator())
# note this is a FixedFormatter
print(ax.xaxis.get_major_formatter())
# these are the ticks that are used
ff = ax.xaxis.get_major_formatter()
print(ff.seq)

这意味着如果您在图表上移动,刻度标签将保持不变,但位置将随机。这与更改xlim的问题相同,即pandas最初设置图表时,刻度标签与数据完全脱离关系

解决此问题的一种(冗长)方法是:

ax.xaxis.set_major_locator(mticker.FixedLocator(np.arange(len(df))))
ax.xaxis.set_major_formatter(mticker.FixedFormatter(df.index))


# note this is a FixedLocator
print(ax.xaxis.get_major_locator())
# note this is a FixedFormatter
print(ax.xaxis.get_major_formatter())

无论您将索引设置为字符串还是日期,这都可以正常工作。
我已经在pandas上创建了一个问题:https://github.com/pydata/pandas/issues/7612

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