无法在 matplotlib 中设置 plt.xticks
Posted
技术标签:
【中文标题】无法在 matplotlib 中设置 plt.xticks【英文标题】:Unable to set plt.xticks in matplotlib 【发布时间】:2018-11-22 04:04:49 【问题描述】:我有一个 pandas 数据框 (df
)
Parameter Date Concentration Unit Prescribed Standard Exceeding Standard? (Yes/No) Remarks
1 NaN 02/01/2017 26.10 µg/m3 NaN NaN NaN
2 NaN 03/01/2017 30.27 µg/m3 NaN NaN NaN
3 NaN 04/01/2017 36.36 µg/m3 NaN NaN NaN
4 NaN 05/01/2017 33.41 µg/m3 NaN NaN NaN
我正在尝试绘制Date vs Concentration
的时间序列图
我使用.to_datetime()
将日期转换为日期时间对象
Parameter Date Concentration Unit Prescribed Standard Exceeding Standard? (Yes/No) Remarks
1 NaN 2017-01-02 26.10 µg/m3 NaN NaN NaN
2 NaN 2017-01-03 30.27 µg/m3 NaN NaN NaN
3 NaN 2017-01-04 36.36 µg/m3 NaN NaN NaN
4 NaN 2017-01-05 33.41 µg/m3 NaN NaN NaN
时间序列图很容易使用:
plt.plot(df["Date"][:322], df["Concentration"][:322], "+", color="red", linewidth=0.5)
但如果我尝试将 xlabels 更改为其他任何内容,比如月份名称,plt.xticks(["Jan", "Feb","Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"])])
我会收到错误消息:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~/.local/lib/python3.6/site-packages/pandas/core/tools/datetimes.py in _convert_listlike(arg, box, format, name, tz)
302 try:
--> 303 values, tz = tslib.datetime_to_datetime64(arg)
304 return DatetimeIndex._simple_new(values, name=name, tz=tz)
pandas/_libs/tslib.pyx in pandas._libs.tslib.datetime_to_datetime64()
TypeError: Unrecognized value type: <class 'str'>
During handling of the above exception, another exception occurred:
OutOfBoundsDatetime Traceback (most recent call last)
~/.local/lib/python3.6/site-packages/pandas/plotting/_converter.py in _convert_1d(values, unit, axis)
310 try:
--> 311 values = tools.to_datetime(values)
312 if isinstance(values, Index):
~/.local/lib/python3.6/site-packages/pandas/core/tools/datetimes.py in to_datetime(arg, errors, dayfirst, yearfirst, utc, box, format, exact, unit, infer_datetime_format, origin)
379 elif is_list_like(arg):
--> 380 result = _convert_listlike(arg, box, format)
381 else:
~/.local/lib/python3.6/site-packages/pandas/core/tools/datetimes.py in _convert_listlike(arg, box, format, name, tz)
305 except (ValueError, TypeError):
--> 306 raise e
307
~/.local/lib/python3.6/site-packages/pandas/core/tools/datetimes.py in _convert_listlike(arg, box, format, name, tz)
293 yearfirst=yearfirst,
--> 294 require_iso8601=require_iso8601
295 )
pandas/_libs/tslib.pyx in pandas._libs.tslib.array_to_datetime()
pandas/_libs/tslib.pyx in pandas._libs.tslib.array_to_datetime()
pandas/_libs/tslib.pyx in pandas._libs.tslib.array_to_datetime()
pandas/_libs/tslib.pyx in pandas._libs.tslib.array_to_datetime()
pandas/_libs/tslib.pyx in pandas._libs.tslib.convert_datetime_to_tsobject()
pandas/_libs/tslib.pyx in pandas._libs.tslib._check_dts_bounds()
OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 1-01-01 00:00:00
During handling of the above exception, another exception occurred:
AttributeError Traceback (most recent call last)
<ipython-input-26-7f51ae7566c4> in <module>()
4
5 plt.plot(df_btm_pm25["Date"][:322], df_btm_pm25["Concentration"][:322], "+", color="red", linewidth=0.5)
----> 6 plt.xticks(["Jan", "Feb","Mar", "Apr", "May", "Jun", "Jul"])#, "Aug", "Sept", "Oct", "Nov", "Dec"])
7 #axes.set_xticks(x)
8 axes.locator_params(nbins=12)
~/.local/lib/python3.6/site-packages/matplotlib/pyplot.py in xticks(*args, **kwargs)
1722 labels = ax.get_xticklabels()
1723 elif len(args)==1:
-> 1724 locs = ax.set_xticks(args[0])
1725 labels = ax.get_xticklabels()
1726 elif len(args)==2:
~/.local/lib/python3.6/site-packages/matplotlib/axes/_base.py in set_xticks(self, ticks, minor)
3206 Default is ``False``.
3207 """
-> 3208 ret = self.xaxis.set_ticks(ticks, minor=minor)
3209 self.stale = True
3210 return ret
~/.local/lib/python3.6/site-packages/matplotlib/axis.py in set_ticks(self, ticks, minor)
1676 """
1677 # XXX if the user changes units, the information will be lost here
-> 1678 ticks = self.convert_units(ticks)
1679 if len(ticks) > 1:
1680 xleft, xright = self.get_view_interval()
~/.local/lib/python3.6/site-packages/matplotlib/axis.py in convert_units(self, x)
1524 return x
1525
-> 1526 ret = self.converter.convert(x, self.units, self)
1527 return ret
1528
~/.local/lib/python3.6/site-packages/pandas/plotting/_converter.py in convert(values, unit, axis)
278 for v in values]
279 else:
--> 280 values = DatetimeConverter._convert_1d(values, unit, axis)
281 return values
282
~/.local/lib/python3.6/site-packages/pandas/plotting/_converter.py in _convert_1d(values, unit, axis)
315 values = [_dt_to_float_ordinal(x) for x in values]
316 except Exception:
--> 317 values = _dt_to_float_ordinal(values)
318
319 return values
~/.local/lib/python3.6/site-packages/pandas/plotting/_converter.py in _dt_to_float_ordinal(dt)
263 base = dates.epoch2num(dt.asi8 / 1.0E9)
264 else:
--> 265 base = dates.date2num(dt)
266 return base
267
~/.local/lib/python3.6/site-packages/matplotlib/dates.py in date2num(d)
450 if not d.size:
451 return d
--> 452 return _to_ordinalf_np_vectorized(d)
453
454
~/.local/lib/python3.6/site-packages/numpy/lib/function_base.py in __call__(self, *args, **kwargs)
2753 vargs.extend([kwargs[_n] for _n in names])
2754
-> 2755 return self._vectorize_call(func=func, args=vargs)
2756
2757 def _get_ufunc_and_otypes(self, func, args):
~/.local/lib/python3.6/site-packages/numpy/lib/function_base.py in _vectorize_call(self, func, args)
2823 res = func()
2824 else:
-> 2825 ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
2826
2827 # Convert args to object arrays first
~/.local/lib/python3.6/site-packages/numpy/lib/function_base.py in _get_ufunc_and_otypes(self, func, args)
2783
2784 inputs = [arg.flat[0] for arg in args]
-> 2785 outputs = func(*inputs)
2786
2787 # Performance note: profiling indicates that -- for simple
~/.local/lib/python3.6/site-packages/matplotlib/dates.py in _to_ordinalf(dt)
253 tzi = UTC
254
--> 255 base = float(dt.toordinal())
256
257 # If it's sufficiently datetime-like, it will have a `date()` method
AttributeError: 'str' object has no attribute 'toordinal'
不过,我可以通过set_xticks
更改刻度。我在这里错过了什么?
【问题讨论】:
我无法轻松地将您的表格转换为代码以提供适当的解决方案 (minimal reproducible example)。所以我只想提一下,您可能应该使用 datetimes 来绘制和 matplotlib.dates 定位器和标签格式化器。 @ImportanceOfBeingErnest 我没有正确获得第二部分。这是 csv 数据文件的链接:pastebin.com/3zuhckN7 【参考方案1】:正如@ImportanceOfBeingErnest 建议的那样,您应该使用locators 重新格式化xtick 标签。我在下面实现了它们:
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.dates as mdates # For formatting dates
fig, ax = plt.subplots(ncols=2, nrows=1, figsize=(15, 4.18))
# Make the original plot
ax[0].plot(df["Date"][:322],
df["Concentration"][:322],
"+", color="red", linewidth=0.5)
ax[0].set_title('Original plot')
# New xticks plot
months = mdates.MonthLocator() # Add tick every month
days = mdates.DayLocator(range(1,32,5)) # Add tick every 5th day in a month
monthFmt = mdates.DateFormatter('%b') # Use abbreviated month name
# Add the locators to the axis
ax[1].xaxis.set_major_locator(months)
ax[1].xaxis.set_major_formatter(monthFmt)
ax[1].xaxis.set_minor_locator(days)
ax[1].plot(df["Date"][:322],
df["Concentration"][:322],
"+", color="red", linewidth=0.5)
ax[1].set_title('Updated xticks')
plt.show()
这里有一些有用的资源:
matplotlib.dates apistrftime()
directives
This example,我大量借鉴
【讨论】:
以上是关于无法在 matplotlib 中设置 plt.xticks的主要内容,如果未能解决你的问题,请参考以下文章