test_datetimelike.py 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563
  1. """ Test cases for time series specific (freq conversion, etc) """
  2. from datetime import date, datetime, time, timedelta
  3. import pickle
  4. import sys
  5. import numpy as np
  6. import pytest
  7. from pandas.compat import PY3, lrange, zip
  8. import pandas.util._test_decorators as td
  9. from pandas import DataFrame, Index, NaT, Series, isna
  10. from pandas.core.indexes.datetimes import bdate_range, date_range
  11. from pandas.core.indexes.period import Period, PeriodIndex, period_range
  12. from pandas.core.indexes.timedeltas import timedelta_range
  13. from pandas.core.resample import DatetimeIndex
  14. from pandas.tests.plotting.common import (
  15. TestPlotBase, _skip_if_no_scipy_gaussian_kde)
  16. import pandas.util.testing as tm
  17. from pandas.util.testing import assert_series_equal, ensure_clean
  18. from pandas.tseries.offsets import DateOffset
  19. @td.skip_if_no_mpl
  20. class TestTSPlot(TestPlotBase):
  21. def setup_method(self, method):
  22. TestPlotBase.setup_method(self, method)
  23. freq = ['S', 'T', 'H', 'D', 'W', 'M', 'Q', 'A']
  24. idx = [period_range('12/31/1999', freq=x, periods=100) for x in freq]
  25. self.period_ser = [Series(np.random.randn(len(x)), x) for x in idx]
  26. self.period_df = [DataFrame(np.random.randn(len(x), 3), index=x,
  27. columns=['A', 'B', 'C'])
  28. for x in idx]
  29. freq = ['S', 'T', 'H', 'D', 'W', 'M', 'Q-DEC', 'A', '1B30Min']
  30. idx = [date_range('12/31/1999', freq=x, periods=100) for x in freq]
  31. self.datetime_ser = [Series(np.random.randn(len(x)), x) for x in idx]
  32. self.datetime_df = [DataFrame(np.random.randn(len(x), 3), index=x,
  33. columns=['A', 'B', 'C'])
  34. for x in idx]
  35. def teardown_method(self, method):
  36. tm.close()
  37. @pytest.mark.slow
  38. def test_ts_plot_with_tz(self):
  39. # GH2877
  40. index = date_range('1/1/2011', periods=2, freq='H',
  41. tz='Europe/Brussels')
  42. ts = Series([188.5, 328.25], index=index)
  43. _check_plot_works(ts.plot)
  44. def test_fontsize_set_correctly(self):
  45. # For issue #8765
  46. df = DataFrame(np.random.randn(10, 9), index=range(10))
  47. fig, ax = self.plt.subplots()
  48. df.plot(fontsize=2, ax=ax)
  49. for label in (ax.get_xticklabels() + ax.get_yticklabels()):
  50. assert label.get_fontsize() == 2
  51. @pytest.mark.slow
  52. def test_frame_inferred(self):
  53. # inferred freq
  54. idx = date_range('1/1/1987', freq='MS', periods=100)
  55. idx = DatetimeIndex(idx.values, freq=None)
  56. df = DataFrame(np.random.randn(len(idx), 3), index=idx)
  57. _check_plot_works(df.plot)
  58. # axes freq
  59. idx = idx[0:40].union(idx[45:99])
  60. df2 = DataFrame(np.random.randn(len(idx), 3), index=idx)
  61. _check_plot_works(df2.plot)
  62. # N > 1
  63. idx = date_range('2008-1-1 00:15:00', freq='15T', periods=10)
  64. idx = DatetimeIndex(idx.values, freq=None)
  65. df = DataFrame(np.random.randn(len(idx), 3), index=idx)
  66. _check_plot_works(df.plot)
  67. def test_is_error_nozeroindex(self):
  68. # GH11858
  69. i = np.array([1, 2, 3])
  70. a = DataFrame(i, index=i)
  71. _check_plot_works(a.plot, xerr=a)
  72. _check_plot_works(a.plot, yerr=a)
  73. def test_nonnumeric_exclude(self):
  74. idx = date_range('1/1/1987', freq='A', periods=3)
  75. df = DataFrame({'A': ["x", "y", "z"], 'B': [1, 2, 3]}, idx)
  76. fig, ax = self.plt.subplots()
  77. df.plot(ax=ax) # it works
  78. assert len(ax.get_lines()) == 1 # B was plotted
  79. self.plt.close(fig)
  80. pytest.raises(TypeError, df['A'].plot)
  81. def test_tsplot_deprecated(self):
  82. from pandas.tseries.plotting import tsplot
  83. _, ax = self.plt.subplots()
  84. ts = tm.makeTimeSeries()
  85. with tm.assert_produces_warning(FutureWarning):
  86. tsplot(ts, self.plt.Axes.plot, ax=ax)
  87. @pytest.mark.slow
  88. def test_tsplot(self):
  89. from pandas.tseries.plotting import tsplot
  90. _, ax = self.plt.subplots()
  91. ts = tm.makeTimeSeries()
  92. def f(*args, **kwds):
  93. with tm.assert_produces_warning(FutureWarning):
  94. return tsplot(s, self.plt.Axes.plot, *args, **kwds)
  95. for s in self.period_ser:
  96. _check_plot_works(f, s.index.freq, ax=ax, series=s)
  97. for s in self.datetime_ser:
  98. _check_plot_works(f, s.index.freq.rule_code, ax=ax, series=s)
  99. for s in self.period_ser:
  100. _check_plot_works(s.plot, ax=ax)
  101. for s in self.datetime_ser:
  102. _check_plot_works(s.plot, ax=ax)
  103. _, ax = self.plt.subplots()
  104. ts.plot(style='k', ax=ax)
  105. color = (0., 0., 0., 1)
  106. assert color == ax.get_lines()[0].get_color()
  107. def test_both_style_and_color(self):
  108. ts = tm.makeTimeSeries()
  109. pytest.raises(ValueError, ts.plot, style='b-', color='#000099')
  110. s = ts.reset_index(drop=True)
  111. pytest.raises(ValueError, s.plot, style='b-', color='#000099')
  112. @pytest.mark.slow
  113. def test_high_freq(self):
  114. freaks = ['ms', 'us']
  115. for freq in freaks:
  116. _, ax = self.plt.subplots()
  117. rng = date_range('1/1/2012', periods=100, freq=freq)
  118. ser = Series(np.random.randn(len(rng)), rng)
  119. _check_plot_works(ser.plot, ax=ax)
  120. def test_get_datevalue(self):
  121. from pandas.plotting._converter import get_datevalue
  122. assert get_datevalue(None, 'D') is None
  123. assert get_datevalue(1987, 'A') == 1987
  124. assert (get_datevalue(Period(1987, 'A'), 'M') ==
  125. Period('1987-12', 'M').ordinal)
  126. assert (get_datevalue('1/1/1987', 'D') ==
  127. Period('1987-1-1', 'D').ordinal)
  128. @pytest.mark.slow
  129. def test_ts_plot_format_coord(self):
  130. def check_format_of_first_point(ax, expected_string):
  131. first_line = ax.get_lines()[0]
  132. first_x = first_line.get_xdata()[0].ordinal
  133. first_y = first_line.get_ydata()[0]
  134. try:
  135. assert expected_string == ax.format_coord(first_x, first_y)
  136. except (ValueError):
  137. pytest.skip("skipping test because issue forming "
  138. "test comparison GH7664")
  139. annual = Series(1, index=date_range('2014-01-01', periods=3,
  140. freq='A-DEC'))
  141. _, ax = self.plt.subplots()
  142. annual.plot(ax=ax)
  143. check_format_of_first_point(ax, 't = 2014 y = 1.000000')
  144. # note this is added to the annual plot already in existence, and
  145. # changes its freq field
  146. daily = Series(1, index=date_range('2014-01-01', periods=3, freq='D'))
  147. daily.plot(ax=ax)
  148. check_format_of_first_point(ax,
  149. 't = 2014-01-01 y = 1.000000')
  150. tm.close()
  151. # tsplot
  152. from pandas.tseries.plotting import tsplot
  153. _, ax = self.plt.subplots()
  154. with tm.assert_produces_warning(FutureWarning):
  155. tsplot(annual, self.plt.Axes.plot, ax=ax)
  156. check_format_of_first_point(ax, 't = 2014 y = 1.000000')
  157. with tm.assert_produces_warning(FutureWarning):
  158. tsplot(daily, self.plt.Axes.plot, ax=ax)
  159. check_format_of_first_point(ax, 't = 2014-01-01 y = 1.000000')
  160. @pytest.mark.slow
  161. def test_line_plot_period_series(self):
  162. for s in self.period_ser:
  163. _check_plot_works(s.plot, s.index.freq)
  164. @pytest.mark.slow
  165. def test_line_plot_datetime_series(self):
  166. for s in self.datetime_ser:
  167. _check_plot_works(s.plot, s.index.freq.rule_code)
  168. @pytest.mark.slow
  169. def test_line_plot_period_frame(self):
  170. for df in self.period_df:
  171. _check_plot_works(df.plot, df.index.freq)
  172. @pytest.mark.slow
  173. def test_line_plot_datetime_frame(self):
  174. for df in self.datetime_df:
  175. freq = df.index.to_period(df.index.freq.rule_code).freq
  176. _check_plot_works(df.plot, freq)
  177. @pytest.mark.slow
  178. def test_line_plot_inferred_freq(self):
  179. for ser in self.datetime_ser:
  180. ser = Series(ser.values, Index(np.asarray(ser.index)))
  181. _check_plot_works(ser.plot, ser.index.inferred_freq)
  182. ser = ser[[0, 3, 5, 6]]
  183. _check_plot_works(ser.plot)
  184. def test_fake_inferred_business(self):
  185. _, ax = self.plt.subplots()
  186. rng = date_range('2001-1-1', '2001-1-10')
  187. ts = Series(lrange(len(rng)), rng)
  188. ts = ts[:3].append(ts[5:])
  189. ts.plot(ax=ax)
  190. assert not hasattr(ax, 'freq')
  191. @pytest.mark.slow
  192. def test_plot_offset_freq(self):
  193. ser = tm.makeTimeSeries()
  194. _check_plot_works(ser.plot)
  195. dr = date_range(ser.index[0], freq='BQS', periods=10)
  196. ser = Series(np.random.randn(len(dr)), dr)
  197. _check_plot_works(ser.plot)
  198. @pytest.mark.slow
  199. def test_plot_multiple_inferred_freq(self):
  200. dr = Index([datetime(2000, 1, 1), datetime(2000, 1, 6), datetime(
  201. 2000, 1, 11)])
  202. ser = Series(np.random.randn(len(dr)), dr)
  203. _check_plot_works(ser.plot)
  204. @pytest.mark.slow
  205. def test_uhf(self):
  206. import pandas.plotting._converter as conv
  207. idx = date_range('2012-6-22 21:59:51.960928', freq='L', periods=500)
  208. df = DataFrame(np.random.randn(len(idx), 2), idx)
  209. _, ax = self.plt.subplots()
  210. df.plot(ax=ax)
  211. axis = ax.get_xaxis()
  212. tlocs = axis.get_ticklocs()
  213. tlabels = axis.get_ticklabels()
  214. for loc, label in zip(tlocs, tlabels):
  215. xp = conv._from_ordinal(loc).strftime('%H:%M:%S.%f')
  216. rs = str(label.get_text())
  217. if len(rs):
  218. assert xp == rs
  219. @pytest.mark.slow
  220. def test_irreg_hf(self):
  221. idx = date_range('2012-6-22 21:59:51', freq='S', periods=100)
  222. df = DataFrame(np.random.randn(len(idx), 2), idx)
  223. irreg = df.iloc[[0, 1, 3, 4]]
  224. _, ax = self.plt.subplots()
  225. irreg.plot(ax=ax)
  226. diffs = Series(ax.get_lines()[0].get_xydata()[:, 0]).diff()
  227. sec = 1. / 24 / 60 / 60
  228. assert (np.fabs(diffs[1:] - [sec, sec * 2, sec]) < 1e-8).all()
  229. _, ax = self.plt.subplots()
  230. df2 = df.copy()
  231. df2.index = df.index.astype(object)
  232. df2.plot(ax=ax)
  233. diffs = Series(ax.get_lines()[0].get_xydata()[:, 0]).diff()
  234. assert (np.fabs(diffs[1:] - sec) < 1e-8).all()
  235. def test_irregular_datetime64_repr_bug(self):
  236. ser = tm.makeTimeSeries()
  237. ser = ser[[0, 1, 2, 7]]
  238. _, ax = self.plt.subplots()
  239. ret = ser.plot(ax=ax)
  240. assert ret is not None
  241. for rs, xp in zip(ax.get_lines()[0].get_xdata(), ser.index):
  242. assert rs == xp
  243. def test_business_freq(self):
  244. bts = tm.makePeriodSeries()
  245. _, ax = self.plt.subplots()
  246. bts.plot(ax=ax)
  247. assert ax.get_lines()[0].get_xydata()[0, 0] == bts.index[0].ordinal
  248. idx = ax.get_lines()[0].get_xdata()
  249. assert PeriodIndex(data=idx).freqstr == 'B'
  250. @pytest.mark.slow
  251. def test_business_freq_convert(self):
  252. bts = tm.makeTimeSeries(300).asfreq('BM')
  253. ts = bts.to_period('M')
  254. _, ax = self.plt.subplots()
  255. bts.plot(ax=ax)
  256. assert ax.get_lines()[0].get_xydata()[0, 0] == ts.index[0].ordinal
  257. idx = ax.get_lines()[0].get_xdata()
  258. assert PeriodIndex(data=idx).freqstr == 'M'
  259. def test_nonzero_base(self):
  260. # GH2571
  261. idx = (date_range('2012-12-20', periods=24, freq='H') + timedelta(
  262. minutes=30))
  263. df = DataFrame(np.arange(24), index=idx)
  264. _, ax = self.plt.subplots()
  265. df.plot(ax=ax)
  266. rs = ax.get_lines()[0].get_xdata()
  267. assert not Index(rs).is_normalized
  268. def test_dataframe(self):
  269. bts = DataFrame({'a': tm.makeTimeSeries()})
  270. _, ax = self.plt.subplots()
  271. bts.plot(ax=ax)
  272. idx = ax.get_lines()[0].get_xdata()
  273. tm.assert_index_equal(bts.index.to_period(), PeriodIndex(idx))
  274. @pytest.mark.slow
  275. def test_axis_limits(self):
  276. def _test(ax):
  277. xlim = ax.get_xlim()
  278. ax.set_xlim(xlim[0] - 5, xlim[1] + 10)
  279. ax.get_figure().canvas.draw()
  280. result = ax.get_xlim()
  281. assert result[0] == xlim[0] - 5
  282. assert result[1] == xlim[1] + 10
  283. # string
  284. expected = (Period('1/1/2000', ax.freq),
  285. Period('4/1/2000', ax.freq))
  286. ax.set_xlim('1/1/2000', '4/1/2000')
  287. ax.get_figure().canvas.draw()
  288. result = ax.get_xlim()
  289. assert int(result[0]) == expected[0].ordinal
  290. assert int(result[1]) == expected[1].ordinal
  291. # datetime
  292. expected = (Period('1/1/2000', ax.freq),
  293. Period('4/1/2000', ax.freq))
  294. ax.set_xlim(datetime(2000, 1, 1), datetime(2000, 4, 1))
  295. ax.get_figure().canvas.draw()
  296. result = ax.get_xlim()
  297. assert int(result[0]) == expected[0].ordinal
  298. assert int(result[1]) == expected[1].ordinal
  299. fig = ax.get_figure()
  300. self.plt.close(fig)
  301. ser = tm.makeTimeSeries()
  302. _, ax = self.plt.subplots()
  303. ser.plot(ax=ax)
  304. _test(ax)
  305. _, ax = self.plt.subplots()
  306. df = DataFrame({'a': ser, 'b': ser + 1})
  307. df.plot(ax=ax)
  308. _test(ax)
  309. df = DataFrame({'a': ser, 'b': ser + 1})
  310. axes = df.plot(subplots=True)
  311. for ax in axes:
  312. _test(ax)
  313. def test_get_finder(self):
  314. import pandas.plotting._converter as conv
  315. assert conv.get_finder('B') == conv._daily_finder
  316. assert conv.get_finder('D') == conv._daily_finder
  317. assert conv.get_finder('M') == conv._monthly_finder
  318. assert conv.get_finder('Q') == conv._quarterly_finder
  319. assert conv.get_finder('A') == conv._annual_finder
  320. assert conv.get_finder('W') == conv._daily_finder
  321. @pytest.mark.slow
  322. def test_finder_daily(self):
  323. day_lst = [10, 40, 252, 400, 950, 2750, 10000]
  324. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  325. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  326. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  327. xpl1 = xpl2 = [Period('1999-1-1', freq='B').ordinal] * len(day_lst)
  328. else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3
  329. xpl1 = [7565, 7564, 7553, 7546, 7518, 7428, 7066]
  330. xpl2 = [7566, 7564, 7554, 7546, 7519, 7429, 7066]
  331. rs1 = []
  332. rs2 = []
  333. for i, n in enumerate(day_lst):
  334. rng = bdate_range('1999-1-1', periods=n)
  335. ser = Series(np.random.randn(len(rng)), rng)
  336. _, ax = self.plt.subplots()
  337. ser.plot(ax=ax)
  338. xaxis = ax.get_xaxis()
  339. rs1.append(xaxis.get_majorticklocs()[0])
  340. vmin, vmax = ax.get_xlim()
  341. ax.set_xlim(vmin + 0.9, vmax)
  342. rs2.append(xaxis.get_majorticklocs()[0])
  343. self.plt.close(ax.get_figure())
  344. assert rs1 == xpl1
  345. assert rs2 == xpl2
  346. @pytest.mark.slow
  347. def test_finder_quarterly(self):
  348. yrs = [3.5, 11]
  349. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  350. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  351. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  352. xpl1 = xpl2 = [Period('1988Q1').ordinal] * len(yrs)
  353. else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3
  354. xpl1 = [68, 68]
  355. xpl2 = [72, 68]
  356. rs1 = []
  357. rs2 = []
  358. for i, n in enumerate(yrs):
  359. rng = period_range('1987Q2', periods=int(n * 4), freq='Q')
  360. ser = Series(np.random.randn(len(rng)), rng)
  361. _, ax = self.plt.subplots()
  362. ser.plot(ax=ax)
  363. xaxis = ax.get_xaxis()
  364. rs1.append(xaxis.get_majorticklocs()[0])
  365. (vmin, vmax) = ax.get_xlim()
  366. ax.set_xlim(vmin + 0.9, vmax)
  367. rs2.append(xaxis.get_majorticklocs()[0])
  368. self.plt.close(ax.get_figure())
  369. assert rs1 == xpl1
  370. assert rs2 == xpl2
  371. @pytest.mark.slow
  372. def test_finder_monthly(self):
  373. yrs = [1.15, 2.5, 4, 11]
  374. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  375. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  376. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  377. xpl1 = xpl2 = [Period('Jan 1988').ordinal] * len(yrs)
  378. else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3
  379. xpl1 = [216, 216, 204, 204]
  380. xpl2 = [216, 216, 216, 204]
  381. rs1 = []
  382. rs2 = []
  383. for i, n in enumerate(yrs):
  384. rng = period_range('1987Q2', periods=int(n * 12), freq='M')
  385. ser = Series(np.random.randn(len(rng)), rng)
  386. _, ax = self.plt.subplots()
  387. ser.plot(ax=ax)
  388. xaxis = ax.get_xaxis()
  389. rs1.append(xaxis.get_majorticklocs()[0])
  390. vmin, vmax = ax.get_xlim()
  391. ax.set_xlim(vmin + 0.9, vmax)
  392. rs2.append(xaxis.get_majorticklocs()[0])
  393. self.plt.close(ax.get_figure())
  394. assert rs1 == xpl1
  395. assert rs2 == xpl2
  396. def test_finder_monthly_long(self):
  397. rng = period_range('1988Q1', periods=24 * 12, freq='M')
  398. ser = Series(np.random.randn(len(rng)), rng)
  399. _, ax = self.plt.subplots()
  400. ser.plot(ax=ax)
  401. xaxis = ax.get_xaxis()
  402. rs = xaxis.get_majorticklocs()[0]
  403. xp = Period('1989Q1', 'M').ordinal
  404. assert rs == xp
  405. @pytest.mark.slow
  406. def test_finder_annual(self):
  407. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  408. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  409. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  410. xp = [1987, 1988, 1990, 1990, 1995, 2020, 2070, 2170]
  411. else: # 2.0.1, 2.1.0, 2.2.2, 2.2.3
  412. xp = [1986, 1986, 1990, 1990, 1995, 2020, 1970, 1970]
  413. xp = [Period(x, freq='A').ordinal for x in xp]
  414. rs = []
  415. for i, nyears in enumerate([5, 10, 19, 49, 99, 199, 599, 1001]):
  416. rng = period_range('1987', periods=nyears, freq='A')
  417. ser = Series(np.random.randn(len(rng)), rng)
  418. _, ax = self.plt.subplots()
  419. ser.plot(ax=ax)
  420. xaxis = ax.get_xaxis()
  421. rs.append(xaxis.get_majorticklocs()[0])
  422. self.plt.close(ax.get_figure())
  423. assert rs == xp
  424. @pytest.mark.slow
  425. def test_finder_minutely(self):
  426. nminutes = 50 * 24 * 60
  427. rng = date_range('1/1/1999', freq='Min', periods=nminutes)
  428. ser = Series(np.random.randn(len(rng)), rng)
  429. _, ax = self.plt.subplots()
  430. ser.plot(ax=ax)
  431. xaxis = ax.get_xaxis()
  432. rs = xaxis.get_majorticklocs()[0]
  433. xp = Period('1/1/1999', freq='Min').ordinal
  434. assert rs == xp
  435. def test_finder_hourly(self):
  436. nhours = 23
  437. rng = date_range('1/1/1999', freq='H', periods=nhours)
  438. ser = Series(np.random.randn(len(rng)), rng)
  439. _, ax = self.plt.subplots()
  440. ser.plot(ax=ax)
  441. xaxis = ax.get_xaxis()
  442. rs = xaxis.get_majorticklocs()[0]
  443. if self.mpl_ge_2_0_1:
  444. xp = Period('1/1/1999', freq='H').ordinal
  445. else: # 2.0.0
  446. xp = Period('1998-12-31 22:00', freq='H').ordinal
  447. assert rs == xp
  448. @pytest.mark.slow
  449. def test_gaps(self):
  450. ts = tm.makeTimeSeries()
  451. ts[5:25] = np.nan
  452. _, ax = self.plt.subplots()
  453. ts.plot(ax=ax)
  454. lines = ax.get_lines()
  455. assert len(lines) == 1
  456. line = lines[0]
  457. data = line.get_xydata()
  458. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  459. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  460. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  461. data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan)
  462. assert isinstance(data, np.ma.core.MaskedArray)
  463. mask = data.mask
  464. assert mask[5:25, 1].all()
  465. self.plt.close(ax.get_figure())
  466. # irregular
  467. ts = tm.makeTimeSeries()
  468. ts = ts[[0, 1, 2, 5, 7, 9, 12, 15, 20]]
  469. ts[2:5] = np.nan
  470. _, ax = self.plt.subplots()
  471. ax = ts.plot(ax=ax)
  472. lines = ax.get_lines()
  473. assert len(lines) == 1
  474. line = lines[0]
  475. data = line.get_xydata()
  476. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  477. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  478. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  479. data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan)
  480. assert isinstance(data, np.ma.core.MaskedArray)
  481. mask = data.mask
  482. assert mask[2:5, 1].all()
  483. self.plt.close(ax.get_figure())
  484. # non-ts
  485. idx = [0, 1, 2, 5, 7, 9, 12, 15, 20]
  486. ser = Series(np.random.randn(len(idx)), idx)
  487. ser[2:5] = np.nan
  488. _, ax = self.plt.subplots()
  489. ser.plot(ax=ax)
  490. lines = ax.get_lines()
  491. assert len(lines) == 1
  492. line = lines[0]
  493. data = line.get_xydata()
  494. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  495. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  496. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  497. data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan)
  498. assert isinstance(data, np.ma.core.MaskedArray)
  499. mask = data.mask
  500. assert mask[2:5, 1].all()
  501. @pytest.mark.slow
  502. def test_gap_upsample(self):
  503. low = tm.makeTimeSeries()
  504. low[5:25] = np.nan
  505. _, ax = self.plt.subplots()
  506. low.plot(ax=ax)
  507. idxh = date_range(low.index[0], low.index[-1], freq='12h')
  508. s = Series(np.random.randn(len(idxh)), idxh)
  509. s.plot(secondary_y=True)
  510. lines = ax.get_lines()
  511. assert len(lines) == 1
  512. assert len(ax.right_ax.get_lines()) == 1
  513. line = lines[0]
  514. data = line.get_xydata()
  515. if (self.mpl_ge_3_0_0 or not self.mpl_ge_2_0_1
  516. or (self.mpl_ge_2_1_0 and not self.mpl_ge_2_2_2)):
  517. # 2.0.0, 2.2.0 (exactly) or >= 3.0.0
  518. data = np.ma.MaskedArray(data, mask=isna(data), fill_value=np.nan)
  519. assert isinstance(data, np.ma.core.MaskedArray)
  520. mask = data.mask
  521. assert mask[5:25, 1].all()
  522. @pytest.mark.slow
  523. def test_secondary_y(self):
  524. ser = Series(np.random.randn(10))
  525. ser2 = Series(np.random.randn(10))
  526. fig, _ = self.plt.subplots()
  527. ax = ser.plot(secondary_y=True)
  528. assert hasattr(ax, 'left_ax')
  529. assert not hasattr(ax, 'right_ax')
  530. axes = fig.get_axes()
  531. line = ax.get_lines()[0]
  532. xp = Series(line.get_ydata(), line.get_xdata())
  533. assert_series_equal(ser, xp)
  534. assert ax.get_yaxis().get_ticks_position() == 'right'
  535. assert not axes[0].get_yaxis().get_visible()
  536. self.plt.close(fig)
  537. _, ax2 = self.plt.subplots()
  538. ser2.plot(ax=ax2)
  539. assert (ax2.get_yaxis().get_ticks_position() ==
  540. self.default_tick_position)
  541. self.plt.close(ax2.get_figure())
  542. ax = ser2.plot()
  543. ax2 = ser.plot(secondary_y=True)
  544. assert ax.get_yaxis().get_visible()
  545. assert not hasattr(ax, 'left_ax')
  546. assert hasattr(ax, 'right_ax')
  547. assert hasattr(ax2, 'left_ax')
  548. assert not hasattr(ax2, 'right_ax')
  549. @pytest.mark.slow
  550. def test_secondary_y_ts(self):
  551. idx = date_range('1/1/2000', periods=10)
  552. ser = Series(np.random.randn(10), idx)
  553. ser2 = Series(np.random.randn(10), idx)
  554. fig, _ = self.plt.subplots()
  555. ax = ser.plot(secondary_y=True)
  556. assert hasattr(ax, 'left_ax')
  557. assert not hasattr(ax, 'right_ax')
  558. axes = fig.get_axes()
  559. line = ax.get_lines()[0]
  560. xp = Series(line.get_ydata(), line.get_xdata()).to_timestamp()
  561. assert_series_equal(ser, xp)
  562. assert ax.get_yaxis().get_ticks_position() == 'right'
  563. assert not axes[0].get_yaxis().get_visible()
  564. self.plt.close(fig)
  565. _, ax2 = self.plt.subplots()
  566. ser2.plot(ax=ax2)
  567. assert (ax2.get_yaxis().get_ticks_position() ==
  568. self.default_tick_position)
  569. self.plt.close(ax2.get_figure())
  570. ax = ser2.plot()
  571. ax2 = ser.plot(secondary_y=True)
  572. assert ax.get_yaxis().get_visible()
  573. @pytest.mark.slow
  574. @td.skip_if_no_scipy
  575. def test_secondary_kde(self):
  576. _skip_if_no_scipy_gaussian_kde()
  577. ser = Series(np.random.randn(10))
  578. fig, ax = self.plt.subplots()
  579. ax = ser.plot(secondary_y=True, kind='density', ax=ax)
  580. assert hasattr(ax, 'left_ax')
  581. assert not hasattr(ax, 'right_ax')
  582. axes = fig.get_axes()
  583. assert axes[1].get_yaxis().get_ticks_position() == 'right'
  584. @pytest.mark.slow
  585. def test_secondary_bar(self):
  586. ser = Series(np.random.randn(10))
  587. fig, ax = self.plt.subplots()
  588. ser.plot(secondary_y=True, kind='bar', ax=ax)
  589. axes = fig.get_axes()
  590. assert axes[1].get_yaxis().get_ticks_position() == 'right'
  591. @pytest.mark.slow
  592. def test_secondary_frame(self):
  593. df = DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c'])
  594. axes = df.plot(secondary_y=['a', 'c'], subplots=True)
  595. assert axes[0].get_yaxis().get_ticks_position() == 'right'
  596. assert (axes[1].get_yaxis().get_ticks_position() ==
  597. self.default_tick_position)
  598. assert axes[2].get_yaxis().get_ticks_position() == 'right'
  599. @pytest.mark.slow
  600. def test_secondary_bar_frame(self):
  601. df = DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c'])
  602. axes = df.plot(kind='bar', secondary_y=['a', 'c'], subplots=True)
  603. assert axes[0].get_yaxis().get_ticks_position() == 'right'
  604. assert (axes[1].get_yaxis().get_ticks_position() ==
  605. self.default_tick_position)
  606. assert axes[2].get_yaxis().get_ticks_position() == 'right'
  607. def test_mixed_freq_regular_first(self):
  608. # TODO
  609. s1 = tm.makeTimeSeries()
  610. s2 = s1[[0, 5, 10, 11, 12, 13, 14, 15]]
  611. # it works!
  612. _, ax = self.plt.subplots()
  613. s1.plot(ax=ax)
  614. ax2 = s2.plot(style='g', ax=ax)
  615. lines = ax2.get_lines()
  616. idx1 = PeriodIndex(lines[0].get_xdata())
  617. idx2 = PeriodIndex(lines[1].get_xdata())
  618. tm.assert_index_equal(idx1, s1.index.to_period('B'))
  619. tm.assert_index_equal(idx2, s2.index.to_period('B'))
  620. left, right = ax2.get_xlim()
  621. pidx = s1.index.to_period()
  622. assert left <= pidx[0].ordinal
  623. assert right >= pidx[-1].ordinal
  624. @pytest.mark.slow
  625. def test_mixed_freq_irregular_first(self):
  626. s1 = tm.makeTimeSeries()
  627. s2 = s1[[0, 5, 10, 11, 12, 13, 14, 15]]
  628. _, ax = self.plt.subplots()
  629. s2.plot(style='g', ax=ax)
  630. s1.plot(ax=ax)
  631. assert not hasattr(ax, 'freq')
  632. lines = ax.get_lines()
  633. x1 = lines[0].get_xdata()
  634. tm.assert_numpy_array_equal(x1, s2.index.astype(object).values)
  635. x2 = lines[1].get_xdata()
  636. tm.assert_numpy_array_equal(x2, s1.index.astype(object).values)
  637. def test_mixed_freq_regular_first_df(self):
  638. # GH 9852
  639. s1 = tm.makeTimeSeries().to_frame()
  640. s2 = s1.iloc[[0, 5, 10, 11, 12, 13, 14, 15], :]
  641. _, ax = self.plt.subplots()
  642. s1.plot(ax=ax)
  643. ax2 = s2.plot(style='g', ax=ax)
  644. lines = ax2.get_lines()
  645. idx1 = PeriodIndex(lines[0].get_xdata())
  646. idx2 = PeriodIndex(lines[1].get_xdata())
  647. assert idx1.equals(s1.index.to_period('B'))
  648. assert idx2.equals(s2.index.to_period('B'))
  649. left, right = ax2.get_xlim()
  650. pidx = s1.index.to_period()
  651. assert left <= pidx[0].ordinal
  652. assert right >= pidx[-1].ordinal
  653. @pytest.mark.slow
  654. def test_mixed_freq_irregular_first_df(self):
  655. # GH 9852
  656. s1 = tm.makeTimeSeries().to_frame()
  657. s2 = s1.iloc[[0, 5, 10, 11, 12, 13, 14, 15], :]
  658. _, ax = self.plt.subplots()
  659. s2.plot(style='g', ax=ax)
  660. s1.plot(ax=ax)
  661. assert not hasattr(ax, 'freq')
  662. lines = ax.get_lines()
  663. x1 = lines[0].get_xdata()
  664. tm.assert_numpy_array_equal(x1, s2.index.astype(object).values)
  665. x2 = lines[1].get_xdata()
  666. tm.assert_numpy_array_equal(x2, s1.index.astype(object).values)
  667. def test_mixed_freq_hf_first(self):
  668. idxh = date_range('1/1/1999', periods=365, freq='D')
  669. idxl = date_range('1/1/1999', periods=12, freq='M')
  670. high = Series(np.random.randn(len(idxh)), idxh)
  671. low = Series(np.random.randn(len(idxl)), idxl)
  672. _, ax = self.plt.subplots()
  673. high.plot(ax=ax)
  674. low.plot(ax=ax)
  675. for l in ax.get_lines():
  676. assert PeriodIndex(data=l.get_xdata()).freq == 'D'
  677. @pytest.mark.slow
  678. def test_mixed_freq_alignment(self):
  679. ts_ind = date_range('2012-01-01 13:00', '2012-01-02', freq='H')
  680. ts_data = np.random.randn(12)
  681. ts = Series(ts_data, index=ts_ind)
  682. ts2 = ts.asfreq('T').interpolate()
  683. _, ax = self.plt.subplots()
  684. ax = ts.plot(ax=ax)
  685. ts2.plot(style='r', ax=ax)
  686. assert ax.lines[0].get_xdata()[0] == ax.lines[1].get_xdata()[0]
  687. @pytest.mark.slow
  688. def test_mixed_freq_lf_first(self):
  689. idxh = date_range('1/1/1999', periods=365, freq='D')
  690. idxl = date_range('1/1/1999', periods=12, freq='M')
  691. high = Series(np.random.randn(len(idxh)), idxh)
  692. low = Series(np.random.randn(len(idxl)), idxl)
  693. _, ax = self.plt.subplots()
  694. low.plot(legend=True, ax=ax)
  695. high.plot(legend=True, ax=ax)
  696. for l in ax.get_lines():
  697. assert PeriodIndex(data=l.get_xdata()).freq == 'D'
  698. leg = ax.get_legend()
  699. assert len(leg.texts) == 2
  700. self.plt.close(ax.get_figure())
  701. idxh = date_range('1/1/1999', periods=240, freq='T')
  702. idxl = date_range('1/1/1999', periods=4, freq='H')
  703. high = Series(np.random.randn(len(idxh)), idxh)
  704. low = Series(np.random.randn(len(idxl)), idxl)
  705. _, ax = self.plt.subplots()
  706. low.plot(ax=ax)
  707. high.plot(ax=ax)
  708. for l in ax.get_lines():
  709. assert PeriodIndex(data=l.get_xdata()).freq == 'T'
  710. def test_mixed_freq_irreg_period(self):
  711. ts = tm.makeTimeSeries()
  712. irreg = ts[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 18, 29]]
  713. rng = period_range('1/3/2000', periods=30, freq='B')
  714. ps = Series(np.random.randn(len(rng)), rng)
  715. _, ax = self.plt.subplots()
  716. irreg.plot(ax=ax)
  717. ps.plot(ax=ax)
  718. def test_mixed_freq_shared_ax(self):
  719. # GH13341, using sharex=True
  720. idx1 = date_range('2015-01-01', periods=3, freq='M')
  721. idx2 = idx1[:1].union(idx1[2:])
  722. s1 = Series(range(len(idx1)), idx1)
  723. s2 = Series(range(len(idx2)), idx2)
  724. fig, (ax1, ax2) = self.plt.subplots(nrows=2, sharex=True)
  725. s1.plot(ax=ax1)
  726. s2.plot(ax=ax2)
  727. assert ax1.freq == 'M'
  728. assert ax2.freq == 'M'
  729. assert (ax1.lines[0].get_xydata()[0, 0] ==
  730. ax2.lines[0].get_xydata()[0, 0])
  731. # using twinx
  732. fig, ax1 = self.plt.subplots()
  733. ax2 = ax1.twinx()
  734. s1.plot(ax=ax1)
  735. s2.plot(ax=ax2)
  736. assert (ax1.lines[0].get_xydata()[0, 0] ==
  737. ax2.lines[0].get_xydata()[0, 0])
  738. # TODO (GH14330, GH14322)
  739. # plotting the irregular first does not yet work
  740. # fig, ax1 = plt.subplots()
  741. # ax2 = ax1.twinx()
  742. # s2.plot(ax=ax1)
  743. # s1.plot(ax=ax2)
  744. # assert (ax1.lines[0].get_xydata()[0, 0] ==
  745. # ax2.lines[0].get_xydata()[0, 0])
  746. def test_nat_handling(self):
  747. _, ax = self.plt.subplots()
  748. dti = DatetimeIndex(['2015-01-01', NaT, '2015-01-03'])
  749. s = Series(range(len(dti)), dti)
  750. s.plot(ax=ax)
  751. xdata = ax.get_lines()[0].get_xdata()
  752. # plot x data is bounded by index values
  753. assert s.index.min() <= Series(xdata).min()
  754. assert Series(xdata).max() <= s.index.max()
  755. @pytest.mark.slow
  756. def test_to_weekly_resampling(self):
  757. idxh = date_range('1/1/1999', periods=52, freq='W')
  758. idxl = date_range('1/1/1999', periods=12, freq='M')
  759. high = Series(np.random.randn(len(idxh)), idxh)
  760. low = Series(np.random.randn(len(idxl)), idxl)
  761. _, ax = self.plt.subplots()
  762. high.plot(ax=ax)
  763. low.plot(ax=ax)
  764. for l in ax.get_lines():
  765. assert PeriodIndex(data=l.get_xdata()).freq == idxh.freq
  766. _, ax = self.plt.subplots()
  767. from pandas.tseries.plotting import tsplot
  768. with tm.assert_produces_warning(FutureWarning):
  769. tsplot(high, self.plt.Axes.plot, ax=ax)
  770. with tm.assert_produces_warning(FutureWarning):
  771. lines = tsplot(low, self.plt.Axes.plot, ax=ax)
  772. for l in lines:
  773. assert PeriodIndex(data=l.get_xdata()).freq == idxh.freq
  774. @pytest.mark.slow
  775. def test_from_weekly_resampling(self):
  776. idxh = date_range('1/1/1999', periods=52, freq='W')
  777. idxl = date_range('1/1/1999', periods=12, freq='M')
  778. high = Series(np.random.randn(len(idxh)), idxh)
  779. low = Series(np.random.randn(len(idxl)), idxl)
  780. _, ax = self.plt.subplots()
  781. low.plot(ax=ax)
  782. high.plot(ax=ax)
  783. expected_h = idxh.to_period().asi8.astype(np.float64)
  784. expected_l = np.array([1514, 1519, 1523, 1527, 1531, 1536, 1540, 1544,
  785. 1549, 1553, 1558, 1562], dtype=np.float64)
  786. for l in ax.get_lines():
  787. assert PeriodIndex(data=l.get_xdata()).freq == idxh.freq
  788. xdata = l.get_xdata(orig=False)
  789. if len(xdata) == 12: # idxl lines
  790. tm.assert_numpy_array_equal(xdata, expected_l)
  791. else:
  792. tm.assert_numpy_array_equal(xdata, expected_h)
  793. tm.close()
  794. _, ax = self.plt.subplots()
  795. from pandas.tseries.plotting import tsplot
  796. with tm.assert_produces_warning(FutureWarning):
  797. tsplot(low, self.plt.Axes.plot, ax=ax)
  798. with tm.assert_produces_warning(FutureWarning):
  799. lines = tsplot(high, self.plt.Axes.plot, ax=ax)
  800. for l in lines:
  801. assert PeriodIndex(data=l.get_xdata()).freq == idxh.freq
  802. xdata = l.get_xdata(orig=False)
  803. if len(xdata) == 12: # idxl lines
  804. tm.assert_numpy_array_equal(xdata, expected_l)
  805. else:
  806. tm.assert_numpy_array_equal(xdata, expected_h)
  807. @pytest.mark.slow
  808. def test_from_resampling_area_line_mixed(self):
  809. idxh = date_range('1/1/1999', periods=52, freq='W')
  810. idxl = date_range('1/1/1999', periods=12, freq='M')
  811. high = DataFrame(np.random.rand(len(idxh), 3),
  812. index=idxh, columns=[0, 1, 2])
  813. low = DataFrame(np.random.rand(len(idxl), 3),
  814. index=idxl, columns=[0, 1, 2])
  815. # low to high
  816. for kind1, kind2 in [('line', 'area'), ('area', 'line')]:
  817. _, ax = self.plt.subplots()
  818. low.plot(kind=kind1, stacked=True, ax=ax)
  819. high.plot(kind=kind2, stacked=True, ax=ax)
  820. # check low dataframe result
  821. expected_x = np.array([1514, 1519, 1523, 1527, 1531, 1536, 1540,
  822. 1544, 1549, 1553, 1558, 1562],
  823. dtype=np.float64)
  824. expected_y = np.zeros(len(expected_x), dtype=np.float64)
  825. for i in range(3):
  826. line = ax.lines[i]
  827. assert PeriodIndex(line.get_xdata()).freq == idxh.freq
  828. tm.assert_numpy_array_equal(line.get_xdata(orig=False),
  829. expected_x)
  830. # check stacked values are correct
  831. expected_y += low[i].values
  832. tm.assert_numpy_array_equal(line.get_ydata(orig=False),
  833. expected_y)
  834. # check high dataframe result
  835. expected_x = idxh.to_period().asi8.astype(np.float64)
  836. expected_y = np.zeros(len(expected_x), dtype=np.float64)
  837. for i in range(3):
  838. line = ax.lines[3 + i]
  839. assert PeriodIndex(data=line.get_xdata()).freq == idxh.freq
  840. tm.assert_numpy_array_equal(line.get_xdata(orig=False),
  841. expected_x)
  842. expected_y += high[i].values
  843. tm.assert_numpy_array_equal(line.get_ydata(orig=False),
  844. expected_y)
  845. # high to low
  846. for kind1, kind2 in [('line', 'area'), ('area', 'line')]:
  847. _, ax = self.plt.subplots()
  848. high.plot(kind=kind1, stacked=True, ax=ax)
  849. low.plot(kind=kind2, stacked=True, ax=ax)
  850. # check high dataframe result
  851. expected_x = idxh.to_period().asi8.astype(np.float64)
  852. expected_y = np.zeros(len(expected_x), dtype=np.float64)
  853. for i in range(3):
  854. line = ax.lines[i]
  855. assert PeriodIndex(data=line.get_xdata()).freq == idxh.freq
  856. tm.assert_numpy_array_equal(line.get_xdata(orig=False),
  857. expected_x)
  858. expected_y += high[i].values
  859. tm.assert_numpy_array_equal(line.get_ydata(orig=False),
  860. expected_y)
  861. # check low dataframe result
  862. expected_x = np.array([1514, 1519, 1523, 1527, 1531, 1536, 1540,
  863. 1544, 1549, 1553, 1558, 1562],
  864. dtype=np.float64)
  865. expected_y = np.zeros(len(expected_x), dtype=np.float64)
  866. for i in range(3):
  867. lines = ax.lines[3 + i]
  868. assert PeriodIndex(data=lines.get_xdata()).freq == idxh.freq
  869. tm.assert_numpy_array_equal(lines.get_xdata(orig=False),
  870. expected_x)
  871. expected_y += low[i].values
  872. tm.assert_numpy_array_equal(lines.get_ydata(orig=False),
  873. expected_y)
  874. @pytest.mark.slow
  875. def test_mixed_freq_second_millisecond(self):
  876. # GH 7772, GH 7760
  877. idxh = date_range('2014-07-01 09:00', freq='S', periods=50)
  878. idxl = date_range('2014-07-01 09:00', freq='100L', periods=500)
  879. high = Series(np.random.randn(len(idxh)), idxh)
  880. low = Series(np.random.randn(len(idxl)), idxl)
  881. # high to low
  882. _, ax = self.plt.subplots()
  883. high.plot(ax=ax)
  884. low.plot(ax=ax)
  885. assert len(ax.get_lines()) == 2
  886. for l in ax.get_lines():
  887. assert PeriodIndex(data=l.get_xdata()).freq == 'L'
  888. tm.close()
  889. # low to high
  890. _, ax = self.plt.subplots()
  891. low.plot(ax=ax)
  892. high.plot(ax=ax)
  893. assert len(ax.get_lines()) == 2
  894. for l in ax.get_lines():
  895. assert PeriodIndex(data=l.get_xdata()).freq == 'L'
  896. @pytest.mark.slow
  897. def test_irreg_dtypes(self):
  898. # date
  899. idx = [date(2000, 1, 1), date(2000, 1, 5), date(2000, 1, 20)]
  900. df = DataFrame(np.random.randn(len(idx), 3), Index(idx, dtype=object))
  901. _check_plot_works(df.plot)
  902. # np.datetime64
  903. idx = date_range('1/1/2000', periods=10)
  904. idx = idx[[0, 2, 5, 9]].astype(object)
  905. df = DataFrame(np.random.randn(len(idx), 3), idx)
  906. _, ax = self.plt.subplots()
  907. _check_plot_works(df.plot, ax=ax)
  908. @pytest.mark.xfail(reason="fails with py2.7.15", strict=False)
  909. @pytest.mark.slow
  910. def test_time(self):
  911. t = datetime(1, 1, 1, 3, 30, 0)
  912. deltas = np.random.randint(1, 20, 3).cumsum()
  913. ts = np.array([(t + timedelta(minutes=int(x))).time() for x in deltas])
  914. df = DataFrame({'a': np.random.randn(len(ts)),
  915. 'b': np.random.randn(len(ts))},
  916. index=ts)
  917. fig, ax = self.plt.subplots()
  918. df.plot(ax=ax)
  919. # verify tick labels
  920. fig.canvas.draw()
  921. ticks = ax.get_xticks()
  922. labels = ax.get_xticklabels()
  923. for t, l in zip(ticks, labels):
  924. m, s = divmod(int(t), 60)
  925. h, m = divmod(m, 60)
  926. rs = l.get_text()
  927. if len(rs) > 0:
  928. if s != 0:
  929. xp = time(h, m, s).strftime('%H:%M:%S')
  930. else:
  931. xp = time(h, m, s).strftime('%H:%M')
  932. assert xp == rs
  933. # change xlim
  934. ax.set_xlim('1:30', '5:00')
  935. # check tick labels again
  936. fig.canvas.draw()
  937. ticks = ax.get_xticks()
  938. labels = ax.get_xticklabels()
  939. for t, l in zip(ticks, labels):
  940. m, s = divmod(int(t), 60)
  941. h, m = divmod(m, 60)
  942. rs = l.get_text()
  943. if len(rs) > 0:
  944. if s != 0:
  945. xp = time(h, m, s).strftime('%H:%M:%S')
  946. else:
  947. xp = time(h, m, s).strftime('%H:%M')
  948. assert xp == rs
  949. @pytest.mark.slow
  950. def test_time_musec(self):
  951. t = datetime(1, 1, 1, 3, 30, 0)
  952. deltas = np.random.randint(1, 20, 3).cumsum()
  953. ts = np.array([(t + timedelta(microseconds=int(x))).time()
  954. for x in deltas])
  955. df = DataFrame({'a': np.random.randn(len(ts)),
  956. 'b': np.random.randn(len(ts))},
  957. index=ts)
  958. fig, ax = self.plt.subplots()
  959. ax = df.plot(ax=ax)
  960. # verify tick labels
  961. fig.canvas.draw()
  962. ticks = ax.get_xticks()
  963. labels = ax.get_xticklabels()
  964. for t, l in zip(ticks, labels):
  965. m, s = divmod(int(t), 60)
  966. us = int(round((t - int(t)) * 1e6))
  967. h, m = divmod(m, 60)
  968. rs = l.get_text()
  969. if len(rs) > 0:
  970. if (us % 1000) != 0:
  971. xp = time(h, m, s, us).strftime('%H:%M:%S.%f')
  972. elif (us // 1000) != 0:
  973. xp = time(h, m, s, us).strftime('%H:%M:%S.%f')[:-3]
  974. elif s != 0:
  975. xp = time(h, m, s, us).strftime('%H:%M:%S')
  976. else:
  977. xp = time(h, m, s, us).strftime('%H:%M')
  978. assert xp == rs
  979. @pytest.mark.slow
  980. def test_secondary_upsample(self):
  981. idxh = date_range('1/1/1999', periods=365, freq='D')
  982. idxl = date_range('1/1/1999', periods=12, freq='M')
  983. high = Series(np.random.randn(len(idxh)), idxh)
  984. low = Series(np.random.randn(len(idxl)), idxl)
  985. _, ax = self.plt.subplots()
  986. low.plot(ax=ax)
  987. ax = high.plot(secondary_y=True, ax=ax)
  988. for l in ax.get_lines():
  989. assert PeriodIndex(l.get_xdata()).freq == 'D'
  990. assert hasattr(ax, 'left_ax')
  991. assert not hasattr(ax, 'right_ax')
  992. for l in ax.left_ax.get_lines():
  993. assert PeriodIndex(l.get_xdata()).freq == 'D'
  994. @pytest.mark.slow
  995. def test_secondary_legend(self):
  996. fig = self.plt.figure()
  997. ax = fig.add_subplot(211)
  998. # ts
  999. df = tm.makeTimeDataFrame()
  1000. df.plot(secondary_y=['A', 'B'], ax=ax)
  1001. leg = ax.get_legend()
  1002. assert len(leg.get_lines()) == 4
  1003. assert leg.get_texts()[0].get_text() == 'A (right)'
  1004. assert leg.get_texts()[1].get_text() == 'B (right)'
  1005. assert leg.get_texts()[2].get_text() == 'C'
  1006. assert leg.get_texts()[3].get_text() == 'D'
  1007. assert ax.right_ax.get_legend() is None
  1008. colors = set()
  1009. for line in leg.get_lines():
  1010. colors.add(line.get_color())
  1011. # TODO: color cycle problems
  1012. assert len(colors) == 4
  1013. self.plt.close(fig)
  1014. fig = self.plt.figure()
  1015. ax = fig.add_subplot(211)
  1016. df.plot(secondary_y=['A', 'C'], mark_right=False, ax=ax)
  1017. leg = ax.get_legend()
  1018. assert len(leg.get_lines()) == 4
  1019. assert leg.get_texts()[0].get_text() == 'A'
  1020. assert leg.get_texts()[1].get_text() == 'B'
  1021. assert leg.get_texts()[2].get_text() == 'C'
  1022. assert leg.get_texts()[3].get_text() == 'D'
  1023. self.plt.close(fig)
  1024. fig, ax = self.plt.subplots()
  1025. df.plot(kind='bar', secondary_y=['A'], ax=ax)
  1026. leg = ax.get_legend()
  1027. assert leg.get_texts()[0].get_text() == 'A (right)'
  1028. assert leg.get_texts()[1].get_text() == 'B'
  1029. self.plt.close(fig)
  1030. fig, ax = self.plt.subplots()
  1031. df.plot(kind='bar', secondary_y=['A'], mark_right=False, ax=ax)
  1032. leg = ax.get_legend()
  1033. assert leg.get_texts()[0].get_text() == 'A'
  1034. assert leg.get_texts()[1].get_text() == 'B'
  1035. self.plt.close(fig)
  1036. fig = self.plt.figure()
  1037. ax = fig.add_subplot(211)
  1038. df = tm.makeTimeDataFrame()
  1039. ax = df.plot(secondary_y=['C', 'D'], ax=ax)
  1040. leg = ax.get_legend()
  1041. assert len(leg.get_lines()) == 4
  1042. assert ax.right_ax.get_legend() is None
  1043. colors = set()
  1044. for line in leg.get_lines():
  1045. colors.add(line.get_color())
  1046. # TODO: color cycle problems
  1047. assert len(colors) == 4
  1048. self.plt.close(fig)
  1049. # non-ts
  1050. df = tm.makeDataFrame()
  1051. fig = self.plt.figure()
  1052. ax = fig.add_subplot(211)
  1053. ax = df.plot(secondary_y=['A', 'B'], ax=ax)
  1054. leg = ax.get_legend()
  1055. assert len(leg.get_lines()) == 4
  1056. assert ax.right_ax.get_legend() is None
  1057. colors = set()
  1058. for line in leg.get_lines():
  1059. colors.add(line.get_color())
  1060. # TODO: color cycle problems
  1061. assert len(colors) == 4
  1062. self.plt.close()
  1063. fig = self.plt.figure()
  1064. ax = fig.add_subplot(211)
  1065. ax = df.plot(secondary_y=['C', 'D'], ax=ax)
  1066. leg = ax.get_legend()
  1067. assert len(leg.get_lines()) == 4
  1068. assert ax.right_ax.get_legend() is None
  1069. colors = set()
  1070. for line in leg.get_lines():
  1071. colors.add(line.get_color())
  1072. # TODO: color cycle problems
  1073. assert len(colors) == 4
  1074. def test_format_date_axis(self):
  1075. rng = date_range('1/1/2012', periods=12, freq='M')
  1076. df = DataFrame(np.random.randn(len(rng), 3), rng)
  1077. _, ax = self.plt.subplots()
  1078. ax = df.plot(ax=ax)
  1079. xaxis = ax.get_xaxis()
  1080. for l in xaxis.get_ticklabels():
  1081. if len(l.get_text()) > 0:
  1082. assert l.get_rotation() == 30
  1083. @pytest.mark.slow
  1084. def test_ax_plot(self):
  1085. x = date_range(start='2012-01-02', periods=10, freq='D')
  1086. y = lrange(len(x))
  1087. _, ax = self.plt.subplots()
  1088. lines = ax.plot(x, y, label='Y')
  1089. tm.assert_index_equal(DatetimeIndex(lines[0].get_xdata()), x)
  1090. @pytest.mark.slow
  1091. def test_mpl_nopandas(self):
  1092. dates = [date(2008, 12, 31), date(2009, 1, 31)]
  1093. values1 = np.arange(10.0, 11.0, 0.5)
  1094. values2 = np.arange(11.0, 12.0, 0.5)
  1095. kw = dict(fmt='-', lw=4)
  1096. _, ax = self.plt.subplots()
  1097. ax.plot_date([x.toordinal() for x in dates], values1, **kw)
  1098. ax.plot_date([x.toordinal() for x in dates], values2, **kw)
  1099. line1, line2 = ax.get_lines()
  1100. exp = np.array([x.toordinal() for x in dates], dtype=np.float64)
  1101. tm.assert_numpy_array_equal(line1.get_xydata()[:, 0], exp)
  1102. exp = np.array([x.toordinal() for x in dates], dtype=np.float64)
  1103. tm.assert_numpy_array_equal(line2.get_xydata()[:, 0], exp)
  1104. @pytest.mark.slow
  1105. def test_irregular_ts_shared_ax_xlim(self):
  1106. # GH 2960
  1107. ts = tm.makeTimeSeries()[:20]
  1108. ts_irregular = ts[[1, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 17, 18]]
  1109. # plot the left section of the irregular series, then the right section
  1110. _, ax = self.plt.subplots()
  1111. ts_irregular[:5].plot(ax=ax)
  1112. ts_irregular[5:].plot(ax=ax)
  1113. # check that axis limits are correct
  1114. left, right = ax.get_xlim()
  1115. assert left <= ts_irregular.index.min().toordinal()
  1116. assert right >= ts_irregular.index.max().toordinal()
  1117. @pytest.mark.slow
  1118. def test_secondary_y_non_ts_xlim(self):
  1119. # GH 3490 - non-timeseries with secondary y
  1120. index_1 = [1, 2, 3, 4]
  1121. index_2 = [5, 6, 7, 8]
  1122. s1 = Series(1, index=index_1)
  1123. s2 = Series(2, index=index_2)
  1124. _, ax = self.plt.subplots()
  1125. s1.plot(ax=ax)
  1126. left_before, right_before = ax.get_xlim()
  1127. s2.plot(secondary_y=True, ax=ax)
  1128. left_after, right_after = ax.get_xlim()
  1129. assert left_before >= left_after
  1130. assert right_before < right_after
  1131. @pytest.mark.slow
  1132. def test_secondary_y_regular_ts_xlim(self):
  1133. # GH 3490 - regular-timeseries with secondary y
  1134. index_1 = date_range(start='2000-01-01', periods=4, freq='D')
  1135. index_2 = date_range(start='2000-01-05', periods=4, freq='D')
  1136. s1 = Series(1, index=index_1)
  1137. s2 = Series(2, index=index_2)
  1138. _, ax = self.plt.subplots()
  1139. s1.plot(ax=ax)
  1140. left_before, right_before = ax.get_xlim()
  1141. s2.plot(secondary_y=True, ax=ax)
  1142. left_after, right_after = ax.get_xlim()
  1143. assert left_before >= left_after
  1144. assert right_before < right_after
  1145. @pytest.mark.slow
  1146. def test_secondary_y_mixed_freq_ts_xlim(self):
  1147. # GH 3490 - mixed frequency timeseries with secondary y
  1148. rng = date_range('2000-01-01', periods=10000, freq='min')
  1149. ts = Series(1, index=rng)
  1150. _, ax = self.plt.subplots()
  1151. ts.plot(ax=ax)
  1152. left_before, right_before = ax.get_xlim()
  1153. ts.resample('D').mean().plot(secondary_y=True, ax=ax)
  1154. left_after, right_after = ax.get_xlim()
  1155. # a downsample should not have changed either limit
  1156. assert left_before == left_after
  1157. assert right_before == right_after
  1158. @pytest.mark.slow
  1159. def test_secondary_y_irregular_ts_xlim(self):
  1160. # GH 3490 - irregular-timeseries with secondary y
  1161. ts = tm.makeTimeSeries()[:20]
  1162. ts_irregular = ts[[1, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 17, 18]]
  1163. _, ax = self.plt.subplots()
  1164. ts_irregular[:5].plot(ax=ax)
  1165. # plot higher-x values on secondary axis
  1166. ts_irregular[5:].plot(secondary_y=True, ax=ax)
  1167. # ensure secondary limits aren't overwritten by plot on primary
  1168. ts_irregular[:5].plot(ax=ax)
  1169. left, right = ax.get_xlim()
  1170. assert left <= ts_irregular.index.min().toordinal()
  1171. assert right >= ts_irregular.index.max().toordinal()
  1172. def test_plot_outofbounds_datetime(self):
  1173. # 2579 - checking this does not raise
  1174. values = [date(1677, 1, 1), date(1677, 1, 2)]
  1175. _, ax = self.plt.subplots()
  1176. ax.plot(values)
  1177. values = [datetime(1677, 1, 1, 12), datetime(1677, 1, 2, 12)]
  1178. ax.plot(values)
  1179. def test_format_timedelta_ticks_narrow(self):
  1180. if self.mpl_ge_2_0_1:
  1181. expected_labels = (['00:00:00.0000000{:0>2d}'.format(i)
  1182. for i in range(10)])
  1183. else: # 2.0.0
  1184. expected_labels = [''] + [
  1185. '00:00:00.00000000{:d}'.format(2 * i)
  1186. for i in range(5)] + ['']
  1187. rng = timedelta_range('0', periods=10, freq='ns')
  1188. df = DataFrame(np.random.randn(len(rng), 3), rng)
  1189. fig, ax = self.plt.subplots()
  1190. df.plot(fontsize=2, ax=ax)
  1191. fig.canvas.draw()
  1192. labels = ax.get_xticklabels()
  1193. result_labels = [x.get_text() for x in labels]
  1194. assert len(result_labels) == len(expected_labels)
  1195. assert result_labels == expected_labels
  1196. def test_format_timedelta_ticks_wide(self):
  1197. expected_labels = [
  1198. '',
  1199. '00:00:00',
  1200. '1 days 03:46:40',
  1201. '2 days 07:33:20',
  1202. '3 days 11:20:00',
  1203. '4 days 15:06:40',
  1204. '5 days 18:53:20',
  1205. '6 days 22:40:00',
  1206. '8 days 02:26:40',
  1207. '9 days 06:13:20',
  1208. ''
  1209. ]
  1210. if self.mpl_ge_2_2_0:
  1211. expected_labels = expected_labels[1:-1]
  1212. elif self.mpl_ge_2_0_1:
  1213. expected_labels = expected_labels[1:-1]
  1214. expected_labels[-1] = ''
  1215. rng = timedelta_range('0', periods=10, freq='1 d')
  1216. df = DataFrame(np.random.randn(len(rng), 3), rng)
  1217. fig, ax = self.plt.subplots()
  1218. ax = df.plot(fontsize=2, ax=ax)
  1219. fig.canvas.draw()
  1220. labels = ax.get_xticklabels()
  1221. result_labels = [x.get_text() for x in labels]
  1222. assert len(result_labels) == len(expected_labels)
  1223. assert result_labels == expected_labels
  1224. def test_timedelta_plot(self):
  1225. # test issue #8711
  1226. s = Series(range(5), timedelta_range('1day', periods=5))
  1227. _, ax = self.plt.subplots()
  1228. _check_plot_works(s.plot, ax=ax)
  1229. # test long period
  1230. index = timedelta_range('1 day 2 hr 30 min 10 s',
  1231. periods=10, freq='1 d')
  1232. s = Series(np.random.randn(len(index)), index)
  1233. _, ax = self.plt.subplots()
  1234. _check_plot_works(s.plot, ax=ax)
  1235. # test short period
  1236. index = timedelta_range('1 day 2 hr 30 min 10 s',
  1237. periods=10, freq='1 ns')
  1238. s = Series(np.random.randn(len(index)), index)
  1239. _, ax = self.plt.subplots()
  1240. _check_plot_works(s.plot, ax=ax)
  1241. def test_hist(self):
  1242. # https://github.com/matplotlib/matplotlib/issues/8459
  1243. rng = date_range('1/1/2011', periods=10, freq='H')
  1244. x = rng
  1245. w1 = np.arange(0, 1, .1)
  1246. w2 = np.arange(0, 1, .1)[::-1]
  1247. _, ax = self.plt.subplots()
  1248. ax.hist([x, x], weights=[w1, w2])
  1249. @pytest.mark.slow
  1250. def test_overlapping_datetime(self):
  1251. # GB 6608
  1252. s1 = Series([1, 2, 3], index=[datetime(1995, 12, 31),
  1253. datetime(2000, 12, 31),
  1254. datetime(2005, 12, 31)])
  1255. s2 = Series([1, 2, 3], index=[datetime(1997, 12, 31),
  1256. datetime(2003, 12, 31),
  1257. datetime(2008, 12, 31)])
  1258. # plot first series, then add the second series to those axes,
  1259. # then try adding the first series again
  1260. _, ax = self.plt.subplots()
  1261. s1.plot(ax=ax)
  1262. s2.plot(ax=ax)
  1263. s1.plot(ax=ax)
  1264. @pytest.mark.xfail(reason="GH9053 matplotlib does not use"
  1265. " ax.xaxis.converter")
  1266. def test_add_matplotlib_datetime64(self):
  1267. # GH9053 - ensure that a plot with PeriodConverter still understands
  1268. # datetime64 data. This still fails because matplotlib overrides the
  1269. # ax.xaxis.converter with a DatetimeConverter
  1270. s = Series(np.random.randn(10),
  1271. index=date_range('1970-01-02', periods=10))
  1272. ax = s.plot()
  1273. ax.plot(s.index, s.values, color='g')
  1274. l1, l2 = ax.lines
  1275. tm.assert_numpy_array_equal(l1.get_xydata(), l2.get_xydata())
  1276. def test_matplotlib_scatter_datetime64(self):
  1277. # https://github.com/matplotlib/matplotlib/issues/11391
  1278. df = DataFrame(np.random.RandomState(0).rand(10, 2),
  1279. columns=["x", "y"])
  1280. df["time"] = date_range("2018-01-01", periods=10, freq="D")
  1281. fig, ax = self.plt.subplots()
  1282. ax.scatter(x="time", y="y", data=df)
  1283. fig.canvas.draw()
  1284. label = ax.get_xticklabels()[0]
  1285. if self.mpl_ge_3_0_0:
  1286. expected = "2017-12-08"
  1287. else:
  1288. expected = "2017-12-12"
  1289. assert label.get_text() == expected
  1290. def _check_plot_works(f, freq=None, series=None, *args, **kwargs):
  1291. import matplotlib.pyplot as plt
  1292. fig = plt.gcf()
  1293. try:
  1294. plt.clf()
  1295. ax = fig.add_subplot(211)
  1296. orig_ax = kwargs.pop('ax', plt.gca())
  1297. orig_axfreq = getattr(orig_ax, 'freq', None)
  1298. ret = f(*args, **kwargs)
  1299. assert ret is not None # do something more intelligent
  1300. ax = kwargs.pop('ax', plt.gca())
  1301. if series is not None:
  1302. dfreq = series.index.freq
  1303. if isinstance(dfreq, DateOffset):
  1304. dfreq = dfreq.rule_code
  1305. if orig_axfreq is None:
  1306. assert ax.freq == dfreq
  1307. if freq is not None and orig_axfreq is None:
  1308. assert ax.freq == freq
  1309. ax = fig.add_subplot(212)
  1310. try:
  1311. kwargs['ax'] = ax
  1312. ret = f(*args, **kwargs)
  1313. assert ret is not None # do something more intelligent
  1314. except Exception:
  1315. pass
  1316. with ensure_clean(return_filelike=True) as path:
  1317. plt.savefig(path)
  1318. # GH18439
  1319. # this is supported only in Python 3 pickle since
  1320. # pickle in Python2 doesn't support instancemethod pickling
  1321. # TODO(statsmodels 0.10.0): Remove the statsmodels check
  1322. # https://github.com/pandas-dev/pandas/issues/24088
  1323. # https://github.com/statsmodels/statsmodels/issues/4772
  1324. if PY3 and 'statsmodels' not in sys.modules:
  1325. with ensure_clean(return_filelike=True) as path:
  1326. pickle.dump(fig, path)
  1327. finally:
  1328. plt.close(fig)