首页 > 解决方案 > 在分组面积图中将日期添加到 x 轴

问题描述

我正在尝试绘制像这样的分组面积图,一个除了 x 轴、y 轴和标题上的标签。

到目前为止,我已经做到 了,在此处输入图像描述但实际数据并未按预期显示在图表中。

当我取消注释该行时area_plot.set_xlim(xmin=datemin, xmax=datemax),数据会显示出来,但 x 轴没有单位。

我不知道是不是因为我想要的 x 轴单位是“日期”,它目前正在将我的日期解释为直数,我需要在ax.xaxis_date()某处包含转换单位,但是当我取消注释时area_plot.xaxis_date(),我收到以下错误:

There was a problem running this cell
ValueError DateFormatter found a value of x=0, which is an illegal date.  This usually occurs because you have not informed the axis that it is plotting dates, e.g., with ax.xaxis_date()

我还尝试取消注释plt.xticks(np.arange(0, len(x1), 12))以使用索引而不是login_month日期来创建适当的 xticks,但它给了我错误:

Error in callback <function install_repl_displayhook.<locals>.post_execute at 0x7f5624809b70> (for post_execute):
There was a problem running this cell
ValueError DateFormatter found a value of x=0, which is an illegal date.  This usually occurs because you have not informed the axis that it is plotting dates, e.g., with ax.xaxis_date() ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/pyplot.py in post_execute()
    147             def post_execute():
    148                 if matplotlib.is_interactive():
--> 149                     draw_all()
    150 
    151             # IPython >= 2

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/_pylab_helpers.py in draw_all(cls, force)
    134         for f_mgr in cls.get_all_fig_managers():
    135             if force or f_mgr.canvas.figure.stale:
--> 136                 f_mgr.canvas.draw_idle()
    137 
    138 atexit.register(Gcf.destroy_all)

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/backend_bases.py in draw_idle(self, *args, **kwargs)
   2053         if not self._is_idle_drawing:
   2054             with self._idle_draw_cntx():
-> 2055                 self.draw(*args, **kwargs)
   2056 
   2057     def draw_cursor(self, event):

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/backends/backend_agg.py in draw(self)
    435             # if toolbar:
    436             #     toolbar.set_cursor(cursors.WAIT)
--> 437             self.figure.draw(self.renderer)
    438             # A GUI class may be need to update a window using this draw, so
    439             # don't forget to call the superclass.

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/figure.py in draw(self, renderer)
   1491 
   1492             mimage._draw_list_compositing_images(
-> 1493                 renderer, self, artists, self.suppressComposite)
   1494 
   1495             renderer.close_group('figure')

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    139     if not_composite or not has_images:
    140         for a in artists:
--> 141             a.draw(renderer)
    142     else:
    143         # Composite any adjacent images together

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2633             renderer.stop_rasterizing()
   2634 
-> 2635         mimage._draw_list_compositing_images(renderer, self, artists)
   2636 
   2637         renderer.close_group('axes')

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    139     if not_composite or not has_images:
    140         for a in artists:
--> 141             a.draw(renderer)
    142     else:
    143         # Composite any adjacent images together

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/axis.py in draw(self, renderer, *args, **kwargs)
   1188         renderer.open_group(__name__)
   1189 
-> 1190         ticks_to_draw = self._update_ticks(renderer)
   1191         ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw,
   1192                                                                 renderer)

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/axis.py in _update_ticks(self, renderer)
   1026 
   1027         interval = self.get_view_interval()
-> 1028         tick_tups = list(self.iter_ticks())  # iter_ticks calls the locator
   1029         if self._smart_bounds and tick_tups:
   1030             # handle inverted limits

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/axis.py in iter_ticks(self)
    973         self.major.formatter.set_locs(majorLocs)
    974         majorLabels = [self.major.formatter(val, i)
--> 975                        for i, val in enumerate(majorLocs)]
    976 
    977         minorLocs = self.minor.locator()

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/axis.py in <listcomp>(.0)
    973         self.major.formatter.set_locs(majorLocs)
    974         majorLabels = [self.major.formatter(val, i)
--> 975                        for i, val in enumerate(majorLocs)]
    976 
    977         minorLocs = self.minor.locator()

/opt/conda/envs/python3/lib/python3.6/site-packages/matplotlib/dates.py in __call__(self, x, pos)
    628     def __call__(self, x, pos=0):
    629         if x == 0:
--> 630             raise ValueError('DateFormatter found a value of x=0, which is '
    631                              'an illegal date.  This usually occurs because '
    632                              'you have not informed the axis that it is '

这是df['login_month'](我试图显示为 x 轴)的样子:

index   login_month
0       2016-01-01 00:00:00
1       2016-02-01 00:00:00
2       2016-03-01 00:00:00
3       2016-04-01 00:00:00
4       2016-05-01 00:00:00
5       2016-06-01 00:00:00
6       2016-07-01 00:00:00
7       2016-08-01 00:00:00
8       2016-09-01 00:00:00
9       2016-10-01 00:00:00
10      2016-11-01 00:00:00
11      2016-12-01 00:00:00
12      2017-01-01 00:00:00
13      2017-02-01 00:00:00
14      2017-03-01 00:00:00
15      2017-04-01 00:00:00
16      2017-05-01 00:00:00
17      2017-06-01 00:00:00
18      2017-07-01 00:00:00
19      2017-08-01 00:00:00
20      2017-09-01 00:00:00
21      2017-10-01 00:00:00
22      2017-11-01 00:00:00
23      2017-12-01 00:00:00
24      2018-01-01 00:00:00
25      2018-02-01 00:00:00
26      2018-03-01 00:00:00
27      2018-04-01 00:00:00
28      2018-05-01 00:00:00
29      2018-06-01 00:00:00
               ...         
1265    2019-09-01 00:00:00
1266    2019-10-01 00:00:00
1267    2019-04-01 00:00:00
1268    2019-05-01 00:00:00
1269    2019-06-01 00:00:00
1270    2019-07-01 00:00:00
1271    2019-08-01 00:00:00
1272    2019-09-01 00:00:00
1273    2019-10-01 00:00:00
1274    2019-05-01 00:00:00
1275    2019-06-01 00:00:00
1276    2019-07-01 00:00:00
1277    2019-08-01 00:00:00
1278    2019-09-01 00:00:00
1279    2019-10-01 00:00:00
1280    2019-06-01 00:00:00
1281    2019-07-01 00:00:00
1282    2019-08-01 00:00:00
1283    2019-09-01 00:00:00
1284    2019-10-01 00:00:00
1285    2019-07-01 00:00:00
1286    2019-08-01 00:00:00
1287    2019-09-01 00:00:00
1288    2019-10-01 00:00:00
1289    2019-08-01 00:00:00
1290    2019-09-01 00:00:00
1291    2019-10-01 00:00:00
1292    2019-09-01 00:00:00
1293    2019-10-01 00:00:00
1294    2019-10-01 00:00:00
Name: login_month, Length: 1295, dtype: object

这是我到目前为止编写的实际代码。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

area_plot = (df.pivot(index='login_month',
          columns='user_month_created',
          values='cumulative_logins')
   .plot.area(figsize=(20,18))
)

#labels
plt.title('cumulative monthly logins by user creation cohort month')
plt.xlabel('login month')
plt.ylabel('cumulative monthly logins (in tens of millions)')

#ticks

# plt.xticks(x, 'bbbb')
years = mdates.YearLocator()   # every year
months = mdates.MonthLocator()  # every month
years_fmt = mdates.DateFormatter('%Y')

# format the ticks
area_plot.xaxis.set_major_locator(years)
area_plot.xaxis.set_major_formatter(years_fmt)
area_plot.xaxis.set_minor_locator(months)

# round to nearest years.
datemin = np.datetime64(df['login_month'][0], 'M')
datemax = np.datetime64(df['login_month'][1294], 'M') + np.timedelta64(1, 'Y')
area_plot.set_xlim(xmin=datemin, xmax=datemax)

x1=df['login_month']
# area_plot.xaxis_date()

# plt.xticks(np.arange(0, len(x1), 12))
plt.yticks(np.arange(0, 11000000, 250000))

plt.grid(True)

这是我得到的(显然)不完整的结果,它完全省略了数据:

在此处输入图像描述

编辑:

df['login_month'] = pd.to_datetime(df['login_month'])在最顶部添加后,我有

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

df['login_month'] = pd.to_datetime(df['login_month'])

area_plot = (df.pivot(index='login_month',
          columns='user_month_created',
          values='cumulative_logins')
   .plot.area(figsize=(20,18))
)

#labels
plt.title('cumulative monthly logins by user creation cohort month')
plt.xlabel('login month')
plt.ylabel('cumulative monthly logins (in tens of millions)')

#ticks
years = mdates.YearLocator()   # every year
months = mdates.MonthLocator()  # every month
years_fmt = mdates.DateFormatter('%Y')

# format the ticks
# x_dates = df['login_month'].dt.strftime('%m-%d').sort_values().unique()
area_plot.xaxis.set_major_locator(years)
# area_plot.xaxis.set_major_formatter(plt.FixedFormatter(x_dates))
area_plot.xaxis.set_major_formatter(years_fmt)
area_plot.xaxis.set_minor_locator(months)

# round to nearest years.
datemin = np.datetime64(df['login_month'][0], 'M')
datemax = np.datetime64(df['login_month'][1294], 'M') + np.timedelta64(1, 'Y')
area_plot.set_xlim(xmin=datemin, xmax=datemax)

# x1=df['login_month']
# area_plot.xaxis_date()

# plt.xticks(np.arange(10, len(x1), 12))
plt.yticks(np.arange(0, 11000000, 250000))
plt.grid(True)

和下图,但 x 轴仍然无法显示:在此处输入图像描述

标签: pythonmatplotlibgraphdata-visualization

解决方案


推荐阅读