test_datetimelike.py 53 KB

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