test_frame.py 126 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314
  1. # coding: utf-8
  2. """ Test cases for DataFrame.plot """
  3. from datetime import date, datetime
  4. import itertools
  5. import string
  6. import warnings
  7. import numpy as np
  8. from numpy.random import rand, randn
  9. import pytest
  10. import pandas.util._test_decorators as td
  11. from pandas.core.dtypes.api import is_list_like
  12. import pandas as pd
  13. from pandas import DataFrame, MultiIndex, PeriodIndex, Series, bdate_range, date_range
  14. import pandas._testing as tm
  15. from pandas.core.arrays import integer_array
  16. from pandas.tests.plotting.common import TestPlotBase, _check_plot_works
  17. from pandas.io.formats.printing import pprint_thing
  18. import pandas.plotting as plotting
  19. @td.skip_if_no_mpl
  20. class TestDataFramePlots(TestPlotBase):
  21. def setup_method(self, method):
  22. TestPlotBase.setup_method(self, method)
  23. import matplotlib as mpl
  24. mpl.rcdefaults()
  25. self.tdf = tm.makeTimeDataFrame()
  26. self.hexbin_df = DataFrame(
  27. {
  28. "A": np.random.uniform(size=20),
  29. "B": np.random.uniform(size=20),
  30. "C": np.arange(20) + np.random.uniform(size=20),
  31. }
  32. )
  33. def _assert_ytickslabels_visibility(self, axes, expected):
  34. for ax, exp in zip(axes, expected):
  35. self._check_visible(ax.get_yticklabels(), visible=exp)
  36. def _assert_xtickslabels_visibility(self, axes, expected):
  37. for ax, exp in zip(axes, expected):
  38. self._check_visible(ax.get_xticklabels(), visible=exp)
  39. @pytest.mark.slow
  40. def test_plot(self):
  41. from pandas.plotting._matplotlib.compat import _mpl_ge_3_1_0
  42. df = self.tdf
  43. _check_plot_works(df.plot, grid=False)
  44. # _check_plot_works adds an ax so catch warning. see GH #13188
  45. with tm.assert_produces_warning(UserWarning):
  46. axes = _check_plot_works(df.plot, subplots=True)
  47. self._check_axes_shape(axes, axes_num=4, layout=(4, 1))
  48. with tm.assert_produces_warning(UserWarning):
  49. axes = _check_plot_works(df.plot, subplots=True, layout=(-1, 2))
  50. self._check_axes_shape(axes, axes_num=4, layout=(2, 2))
  51. with tm.assert_produces_warning(UserWarning):
  52. axes = _check_plot_works(df.plot, subplots=True, use_index=False)
  53. self._check_axes_shape(axes, axes_num=4, layout=(4, 1))
  54. df = DataFrame({"x": [1, 2], "y": [3, 4]})
  55. if _mpl_ge_3_1_0():
  56. msg = "'Line2D' object has no property 'blarg'"
  57. else:
  58. msg = "Unknown property blarg"
  59. with pytest.raises(AttributeError, match=msg):
  60. df.plot.line(blarg=True)
  61. df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10]))
  62. _check_plot_works(df.plot, use_index=True)
  63. _check_plot_works(df.plot, sort_columns=False)
  64. _check_plot_works(df.plot, yticks=[1, 5, 10])
  65. _check_plot_works(df.plot, xticks=[1, 5, 10])
  66. _check_plot_works(df.plot, ylim=(-100, 100), xlim=(-100, 100))
  67. with tm.assert_produces_warning(UserWarning):
  68. _check_plot_works(df.plot, subplots=True, title="blah")
  69. # We have to redo it here because _check_plot_works does two plots,
  70. # once without an ax kwarg and once with an ax kwarg and the new sharex
  71. # behaviour does not remove the visibility of the latter axis (as ax is
  72. # present). see: https://github.com/pandas-dev/pandas/issues/9737
  73. axes = df.plot(subplots=True, title="blah")
  74. self._check_axes_shape(axes, axes_num=3, layout=(3, 1))
  75. # axes[0].figure.savefig("test.png")
  76. for ax in axes[:2]:
  77. self._check_visible(ax.xaxis) # xaxis must be visible for grid
  78. self._check_visible(ax.get_xticklabels(), visible=False)
  79. self._check_visible(ax.get_xticklabels(minor=True), visible=False)
  80. self._check_visible([ax.xaxis.get_label()], visible=False)
  81. for ax in [axes[2]]:
  82. self._check_visible(ax.xaxis)
  83. self._check_visible(ax.get_xticklabels())
  84. self._check_visible([ax.xaxis.get_label()])
  85. self._check_ticks_props(ax, xrot=0)
  86. _check_plot_works(df.plot, title="blah")
  87. tuples = zip(string.ascii_letters[:10], range(10))
  88. df = DataFrame(np.random.rand(10, 3), index=MultiIndex.from_tuples(tuples))
  89. _check_plot_works(df.plot, use_index=True)
  90. # unicode
  91. index = MultiIndex.from_tuples(
  92. [
  93. ("\u03b1", 0),
  94. ("\u03b1", 1),
  95. ("\u03b2", 2),
  96. ("\u03b2", 3),
  97. ("\u03b3", 4),
  98. ("\u03b3", 5),
  99. ("\u03b4", 6),
  100. ("\u03b4", 7),
  101. ],
  102. names=["i0", "i1"],
  103. )
  104. columns = MultiIndex.from_tuples(
  105. [("bar", "\u0394"), ("bar", "\u0395")], names=["c0", "c1"]
  106. )
  107. df = DataFrame(np.random.randint(0, 10, (8, 2)), columns=columns, index=index)
  108. _check_plot_works(df.plot, title="\u03A3")
  109. # GH 6951
  110. # Test with single column
  111. df = DataFrame({"x": np.random.rand(10)})
  112. axes = _check_plot_works(df.plot.bar, subplots=True)
  113. self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  114. axes = _check_plot_works(df.plot.bar, subplots=True, layout=(-1, 1))
  115. self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  116. # When ax is supplied and required number of axes is 1,
  117. # passed ax should be used:
  118. fig, ax = self.plt.subplots()
  119. axes = df.plot.bar(subplots=True, ax=ax)
  120. assert len(axes) == 1
  121. result = ax.axes
  122. assert result is axes[0]
  123. def test_integer_array_plot(self):
  124. # GH 25587
  125. arr = integer_array([1, 2, 3, 4], dtype="UInt32")
  126. s = Series(arr)
  127. _check_plot_works(s.plot.line)
  128. _check_plot_works(s.plot.bar)
  129. _check_plot_works(s.plot.hist)
  130. _check_plot_works(s.plot.pie)
  131. df = DataFrame({"x": arr, "y": arr})
  132. _check_plot_works(df.plot.line)
  133. _check_plot_works(df.plot.bar)
  134. _check_plot_works(df.plot.hist)
  135. _check_plot_works(df.plot.pie, y="y")
  136. _check_plot_works(df.plot.scatter, x="x", y="y")
  137. _check_plot_works(df.plot.hexbin, x="x", y="y")
  138. def test_mpl2_color_cycle_str(self):
  139. # GH 15516
  140. colors = ["C" + str(x) for x in range(10)]
  141. df = DataFrame(randn(10, 3), columns=["a", "b", "c"])
  142. for c in colors:
  143. _check_plot_works(df.plot, color=c)
  144. def test_color_single_series_list(self):
  145. # GH 3486
  146. df = DataFrame({"A": [1, 2, 3]})
  147. _check_plot_works(df.plot, color=["red"])
  148. def test_rgb_tuple_color(self):
  149. # GH 16695
  150. df = DataFrame({"x": [1, 2], "y": [3, 4]})
  151. _check_plot_works(df.plot, x="x", y="y", color=(1, 0, 0))
  152. _check_plot_works(df.plot, x="x", y="y", color=(1, 0, 0, 0.5))
  153. def test_color_empty_string(self):
  154. df = DataFrame(randn(10, 2))
  155. with pytest.raises(ValueError):
  156. df.plot(color="")
  157. def test_color_and_style_arguments(self):
  158. df = DataFrame({"x": [1, 2], "y": [3, 4]})
  159. # passing both 'color' and 'style' arguments should be allowed
  160. # if there is no color symbol in the style strings:
  161. ax = df.plot(color=["red", "black"], style=["-", "--"])
  162. # check that the linestyles are correctly set:
  163. linestyle = [line.get_linestyle() for line in ax.lines]
  164. assert linestyle == ["-", "--"]
  165. # check that the colors are correctly set:
  166. color = [line.get_color() for line in ax.lines]
  167. assert color == ["red", "black"]
  168. # passing both 'color' and 'style' arguments should not be allowed
  169. # if there is a color symbol in the style strings:
  170. with pytest.raises(ValueError):
  171. df.plot(color=["red", "black"], style=["k-", "r--"])
  172. def test_nonnumeric_exclude(self):
  173. df = DataFrame({"A": ["x", "y", "z"], "B": [1, 2, 3]})
  174. ax = df.plot()
  175. assert len(ax.get_lines()) == 1 # B was plotted
  176. @pytest.mark.slow
  177. def test_implicit_label(self):
  178. df = DataFrame(randn(10, 3), columns=["a", "b", "c"])
  179. ax = df.plot(x="a", y="b")
  180. self._check_text_labels(ax.xaxis.get_label(), "a")
  181. @pytest.mark.slow
  182. def test_donot_overwrite_index_name(self):
  183. # GH 8494
  184. df = DataFrame(randn(2, 2), columns=["a", "b"])
  185. df.index.name = "NAME"
  186. df.plot(y="b", label="LABEL")
  187. assert df.index.name == "NAME"
  188. @pytest.mark.slow
  189. def test_plot_xy(self):
  190. # columns.inferred_type == 'string'
  191. df = self.tdf
  192. self._check_data(df.plot(x=0, y=1), df.set_index("A")["B"].plot())
  193. self._check_data(df.plot(x=0), df.set_index("A").plot())
  194. self._check_data(df.plot(y=0), df.B.plot())
  195. self._check_data(df.plot(x="A", y="B"), df.set_index("A").B.plot())
  196. self._check_data(df.plot(x="A"), df.set_index("A").plot())
  197. self._check_data(df.plot(y="B"), df.B.plot())
  198. # columns.inferred_type == 'integer'
  199. df.columns = np.arange(1, len(df.columns) + 1)
  200. self._check_data(df.plot(x=1, y=2), df.set_index(1)[2].plot())
  201. self._check_data(df.plot(x=1), df.set_index(1).plot())
  202. self._check_data(df.plot(y=1), df[1].plot())
  203. # figsize and title
  204. ax = df.plot(x=1, y=2, title="Test", figsize=(16, 8))
  205. self._check_text_labels(ax.title, "Test")
  206. self._check_axes_shape(ax, axes_num=1, layout=(1, 1), figsize=(16.0, 8.0))
  207. # columns.inferred_type == 'mixed'
  208. # TODO add MultiIndex test
  209. @pytest.mark.slow
  210. @pytest.mark.parametrize(
  211. "input_log, expected_log", [(True, "log"), ("sym", "symlog")]
  212. )
  213. def test_logscales(self, input_log, expected_log):
  214. df = DataFrame({"a": np.arange(100)}, index=np.arange(100))
  215. ax = df.plot(logy=input_log)
  216. self._check_ax_scales(ax, yaxis=expected_log)
  217. assert ax.get_yscale() == expected_log
  218. ax = df.plot(logx=input_log)
  219. self._check_ax_scales(ax, xaxis=expected_log)
  220. assert ax.get_xscale() == expected_log
  221. ax = df.plot(loglog=input_log)
  222. self._check_ax_scales(ax, xaxis=expected_log, yaxis=expected_log)
  223. assert ax.get_xscale() == expected_log
  224. assert ax.get_yscale() == expected_log
  225. @pytest.mark.parametrize("input_param", ["logx", "logy", "loglog"])
  226. def test_invalid_logscale(self, input_param):
  227. # GH: 24867
  228. df = DataFrame({"a": np.arange(100)}, index=np.arange(100))
  229. msg = "Boolean, None and 'sym' are valid options, 'sm' is given."
  230. with pytest.raises(ValueError, match=msg):
  231. df.plot(**{input_param: "sm"})
  232. @pytest.mark.slow
  233. def test_xcompat(self):
  234. import pandas as pd
  235. df = self.tdf
  236. ax = df.plot(x_compat=True)
  237. lines = ax.get_lines()
  238. assert not isinstance(lines[0].get_xdata(), PeriodIndex)
  239. tm.close()
  240. pd.plotting.plot_params["xaxis.compat"] = True
  241. ax = df.plot()
  242. lines = ax.get_lines()
  243. assert not isinstance(lines[0].get_xdata(), PeriodIndex)
  244. tm.close()
  245. pd.plotting.plot_params["x_compat"] = False
  246. ax = df.plot()
  247. lines = ax.get_lines()
  248. assert not isinstance(lines[0].get_xdata(), PeriodIndex)
  249. assert isinstance(PeriodIndex(lines[0].get_xdata()), PeriodIndex)
  250. tm.close()
  251. # useful if you're plotting a bunch together
  252. with pd.plotting.plot_params.use("x_compat", True):
  253. ax = df.plot()
  254. lines = ax.get_lines()
  255. assert not isinstance(lines[0].get_xdata(), PeriodIndex)
  256. tm.close()
  257. ax = df.plot()
  258. lines = ax.get_lines()
  259. assert not isinstance(lines[0].get_xdata(), PeriodIndex)
  260. assert isinstance(PeriodIndex(lines[0].get_xdata()), PeriodIndex)
  261. def test_period_compat(self):
  262. # GH 9012
  263. # period-array conversions
  264. df = DataFrame(
  265. np.random.rand(21, 2),
  266. index=bdate_range(datetime(2000, 1, 1), datetime(2000, 1, 31)),
  267. columns=["a", "b"],
  268. )
  269. df.plot()
  270. self.plt.axhline(y=0)
  271. tm.close()
  272. def test_unsorted_index(self):
  273. df = DataFrame(
  274. {"y": np.arange(100)}, index=np.arange(99, -1, -1), dtype=np.int64
  275. )
  276. ax = df.plot()
  277. lines = ax.get_lines()[0]
  278. rs = lines.get_xydata()
  279. rs = Series(rs[:, 1], rs[:, 0], dtype=np.int64, name="y")
  280. tm.assert_series_equal(rs, df.y, check_index_type=False)
  281. tm.close()
  282. df.index = pd.Index(np.arange(99, -1, -1), dtype=np.float64)
  283. ax = df.plot()
  284. lines = ax.get_lines()[0]
  285. rs = lines.get_xydata()
  286. rs = Series(rs[:, 1], rs[:, 0], dtype=np.int64, name="y")
  287. tm.assert_series_equal(rs, df.y)
  288. def test_unsorted_index_lims(self):
  289. df = DataFrame({"y": [0.0, 1.0, 2.0, 3.0]}, index=[1.0, 0.0, 3.0, 2.0])
  290. ax = df.plot()
  291. xmin, xmax = ax.get_xlim()
  292. lines = ax.get_lines()
  293. assert xmin <= np.nanmin(lines[0].get_data()[0])
  294. assert xmax >= np.nanmax(lines[0].get_data()[0])
  295. df = DataFrame(
  296. {"y": [0.0, 1.0, np.nan, 3.0, 4.0, 5.0, 6.0]},
  297. index=[1.0, 0.0, 3.0, 2.0, np.nan, 3.0, 2.0],
  298. )
  299. ax = df.plot()
  300. xmin, xmax = ax.get_xlim()
  301. lines = ax.get_lines()
  302. assert xmin <= np.nanmin(lines[0].get_data()[0])
  303. assert xmax >= np.nanmax(lines[0].get_data()[0])
  304. df = DataFrame({"y": [0.0, 1.0, 2.0, 3.0], "z": [91.0, 90.0, 93.0, 92.0]})
  305. ax = df.plot(x="z", y="y")
  306. xmin, xmax = ax.get_xlim()
  307. lines = ax.get_lines()
  308. assert xmin <= np.nanmin(lines[0].get_data()[0])
  309. assert xmax >= np.nanmax(lines[0].get_data()[0])
  310. @pytest.mark.slow
  311. def test_subplots(self):
  312. df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10]))
  313. for kind in ["bar", "barh", "line", "area"]:
  314. axes = df.plot(kind=kind, subplots=True, sharex=True, legend=True)
  315. self._check_axes_shape(axes, axes_num=3, layout=(3, 1))
  316. assert axes.shape == (3,)
  317. for ax, column in zip(axes, df.columns):
  318. self._check_legend_labels(ax, labels=[pprint_thing(column)])
  319. for ax in axes[:-2]:
  320. self._check_visible(ax.xaxis) # xaxis must be visible for grid
  321. self._check_visible(ax.get_xticklabels(), visible=False)
  322. if not (kind == "bar" and self.mpl_ge_3_1_0):
  323. # change https://github.com/pandas-dev/pandas/issues/26714
  324. self._check_visible(ax.get_xticklabels(minor=True), visible=False)
  325. self._check_visible(ax.xaxis.get_label(), visible=False)
  326. self._check_visible(ax.get_yticklabels())
  327. self._check_visible(axes[-1].xaxis)
  328. self._check_visible(axes[-1].get_xticklabels())
  329. self._check_visible(axes[-1].get_xticklabels(minor=True))
  330. self._check_visible(axes[-1].xaxis.get_label())
  331. self._check_visible(axes[-1].get_yticklabels())
  332. axes = df.plot(kind=kind, subplots=True, sharex=False)
  333. for ax in axes:
  334. self._check_visible(ax.xaxis)
  335. self._check_visible(ax.get_xticklabels())
  336. self._check_visible(ax.get_xticklabels(minor=True))
  337. self._check_visible(ax.xaxis.get_label())
  338. self._check_visible(ax.get_yticklabels())
  339. axes = df.plot(kind=kind, subplots=True, legend=False)
  340. for ax in axes:
  341. assert ax.get_legend() is None
  342. def test_groupby_boxplot_sharey(self):
  343. # https://github.com/pandas-dev/pandas/issues/20968
  344. # sharey can now be switched check whether the right
  345. # pair of axes is turned on or off
  346. df = DataFrame(
  347. {
  348. "a": [-1.43, -0.15, -3.70, -1.43, -0.14],
  349. "b": [0.56, 0.84, 0.29, 0.56, 0.85],
  350. "c": [0, 1, 2, 3, 1],
  351. },
  352. index=[0, 1, 2, 3, 4],
  353. )
  354. # behavior without keyword
  355. axes = df.groupby("c").boxplot()
  356. expected = [True, False, True, False]
  357. self._assert_ytickslabels_visibility(axes, expected)
  358. # set sharey=True should be identical
  359. axes = df.groupby("c").boxplot(sharey=True)
  360. expected = [True, False, True, False]
  361. self._assert_ytickslabels_visibility(axes, expected)
  362. # sharey=False, all yticklabels should be visible
  363. axes = df.groupby("c").boxplot(sharey=False)
  364. expected = [True, True, True, True]
  365. self._assert_ytickslabels_visibility(axes, expected)
  366. def test_groupby_boxplot_sharex(self):
  367. # https://github.com/pandas-dev/pandas/issues/20968
  368. # sharex can now be switched check whether the right
  369. # pair of axes is turned on or off
  370. df = DataFrame(
  371. {
  372. "a": [-1.43, -0.15, -3.70, -1.43, -0.14],
  373. "b": [0.56, 0.84, 0.29, 0.56, 0.85],
  374. "c": [0, 1, 2, 3, 1],
  375. },
  376. index=[0, 1, 2, 3, 4],
  377. )
  378. # behavior without keyword
  379. axes = df.groupby("c").boxplot()
  380. expected = [True, True, True, True]
  381. self._assert_xtickslabels_visibility(axes, expected)
  382. # set sharex=False should be identical
  383. axes = df.groupby("c").boxplot(sharex=False)
  384. expected = [True, True, True, True]
  385. self._assert_xtickslabels_visibility(axes, expected)
  386. # sharex=True, yticklabels should be visible
  387. # only for bottom plots
  388. axes = df.groupby("c").boxplot(sharex=True)
  389. expected = [False, False, True, True]
  390. self._assert_xtickslabels_visibility(axes, expected)
  391. @pytest.mark.slow
  392. def test_subplots_timeseries(self):
  393. idx = date_range(start="2014-07-01", freq="M", periods=10)
  394. df = DataFrame(np.random.rand(10, 3), index=idx)
  395. for kind in ["line", "area"]:
  396. axes = df.plot(kind=kind, subplots=True, sharex=True)
  397. self._check_axes_shape(axes, axes_num=3, layout=(3, 1))
  398. for ax in axes[:-2]:
  399. # GH 7801
  400. self._check_visible(ax.xaxis) # xaxis must be visible for grid
  401. self._check_visible(ax.get_xticklabels(), visible=False)
  402. self._check_visible(ax.get_xticklabels(minor=True), visible=False)
  403. self._check_visible(ax.xaxis.get_label(), visible=False)
  404. self._check_visible(ax.get_yticklabels())
  405. self._check_visible(axes[-1].xaxis)
  406. self._check_visible(axes[-1].get_xticklabels())
  407. self._check_visible(axes[-1].get_xticklabels(minor=True))
  408. self._check_visible(axes[-1].xaxis.get_label())
  409. self._check_visible(axes[-1].get_yticklabels())
  410. self._check_ticks_props(axes, xrot=0)
  411. axes = df.plot(kind=kind, subplots=True, sharex=False, rot=45, fontsize=7)
  412. for ax in axes:
  413. self._check_visible(ax.xaxis)
  414. self._check_visible(ax.get_xticklabels())
  415. self._check_visible(ax.get_xticklabels(minor=True))
  416. self._check_visible(ax.xaxis.get_label())
  417. self._check_visible(ax.get_yticklabels())
  418. self._check_ticks_props(ax, xlabelsize=7, xrot=45, ylabelsize=7)
  419. def test_subplots_timeseries_y_axis(self):
  420. # GH16953
  421. data = {
  422. "numeric": np.array([1, 2, 5]),
  423. "timedelta": [
  424. pd.Timedelta(-10, unit="s"),
  425. pd.Timedelta(10, unit="m"),
  426. pd.Timedelta(10, unit="h"),
  427. ],
  428. "datetime_no_tz": [
  429. pd.to_datetime("2017-08-01 00:00:00"),
  430. pd.to_datetime("2017-08-01 02:00:00"),
  431. pd.to_datetime("2017-08-02 00:00:00"),
  432. ],
  433. "datetime_all_tz": [
  434. pd.to_datetime("2017-08-01 00:00:00", utc=True),
  435. pd.to_datetime("2017-08-01 02:00:00", utc=True),
  436. pd.to_datetime("2017-08-02 00:00:00", utc=True),
  437. ],
  438. "text": ["This", "should", "fail"],
  439. }
  440. testdata = DataFrame(data)
  441. ax_numeric = testdata.plot(y="numeric")
  442. assert (
  443. ax_numeric.get_lines()[0].get_data()[1] == testdata["numeric"].values
  444. ).all()
  445. ax_timedelta = testdata.plot(y="timedelta")
  446. assert (
  447. ax_timedelta.get_lines()[0].get_data()[1] == testdata["timedelta"].values
  448. ).all()
  449. ax_datetime_no_tz = testdata.plot(y="datetime_no_tz")
  450. assert (
  451. ax_datetime_no_tz.get_lines()[0].get_data()[1]
  452. == testdata["datetime_no_tz"].values
  453. ).all()
  454. ax_datetime_all_tz = testdata.plot(y="datetime_all_tz")
  455. assert (
  456. ax_datetime_all_tz.get_lines()[0].get_data()[1]
  457. == testdata["datetime_all_tz"].values
  458. ).all()
  459. msg = "no numeric data to plot"
  460. with pytest.raises(TypeError, match=msg):
  461. testdata.plot(y="text")
  462. @pytest.mark.xfail(reason="not support for period, categorical, datetime_mixed_tz")
  463. def test_subplots_timeseries_y_axis_not_supported(self):
  464. """
  465. This test will fail for:
  466. period:
  467. since period isn't yet implemented in ``select_dtypes``
  468. and because it will need a custom value converter +
  469. tick formatter (as was done for x-axis plots)
  470. categorical:
  471. because it will need a custom value converter +
  472. tick formatter (also doesn't work for x-axis, as of now)
  473. datetime_mixed_tz:
  474. because of the way how pandas handles ``Series`` of
  475. ``datetime`` objects with different timezone,
  476. generally converting ``datetime`` objects in a tz-aware
  477. form could help with this problem
  478. """
  479. data = {
  480. "numeric": np.array([1, 2, 5]),
  481. "period": [
  482. pd.Period("2017-08-01 00:00:00", freq="H"),
  483. pd.Period("2017-08-01 02:00", freq="H"),
  484. pd.Period("2017-08-02 00:00:00", freq="H"),
  485. ],
  486. "categorical": pd.Categorical(
  487. ["c", "b", "a"], categories=["a", "b", "c"], ordered=False
  488. ),
  489. "datetime_mixed_tz": [
  490. pd.to_datetime("2017-08-01 00:00:00", utc=True),
  491. pd.to_datetime("2017-08-01 02:00:00"),
  492. pd.to_datetime("2017-08-02 00:00:00"),
  493. ],
  494. }
  495. testdata = pd.DataFrame(data)
  496. ax_period = testdata.plot(x="numeric", y="period")
  497. assert (
  498. ax_period.get_lines()[0].get_data()[1] == testdata["period"].values
  499. ).all()
  500. ax_categorical = testdata.plot(x="numeric", y="categorical")
  501. assert (
  502. ax_categorical.get_lines()[0].get_data()[1]
  503. == testdata["categorical"].values
  504. ).all()
  505. ax_datetime_mixed_tz = testdata.plot(x="numeric", y="datetime_mixed_tz")
  506. assert (
  507. ax_datetime_mixed_tz.get_lines()[0].get_data()[1]
  508. == testdata["datetime_mixed_tz"].values
  509. ).all()
  510. @pytest.mark.slow
  511. def test_subplots_layout(self):
  512. # GH 6667
  513. df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10]))
  514. axes = df.plot(subplots=True, layout=(2, 2))
  515. self._check_axes_shape(axes, axes_num=3, layout=(2, 2))
  516. assert axes.shape == (2, 2)
  517. axes = df.plot(subplots=True, layout=(-1, 2))
  518. self._check_axes_shape(axes, axes_num=3, layout=(2, 2))
  519. assert axes.shape == (2, 2)
  520. axes = df.plot(subplots=True, layout=(2, -1))
  521. self._check_axes_shape(axes, axes_num=3, layout=(2, 2))
  522. assert axes.shape == (2, 2)
  523. axes = df.plot(subplots=True, layout=(1, 4))
  524. self._check_axes_shape(axes, axes_num=3, layout=(1, 4))
  525. assert axes.shape == (1, 4)
  526. axes = df.plot(subplots=True, layout=(-1, 4))
  527. self._check_axes_shape(axes, axes_num=3, layout=(1, 4))
  528. assert axes.shape == (1, 4)
  529. axes = df.plot(subplots=True, layout=(4, -1))
  530. self._check_axes_shape(axes, axes_num=3, layout=(4, 1))
  531. assert axes.shape == (4, 1)
  532. with pytest.raises(ValueError):
  533. df.plot(subplots=True, layout=(1, 1))
  534. with pytest.raises(ValueError):
  535. df.plot(subplots=True, layout=(-1, -1))
  536. # single column
  537. df = DataFrame(np.random.rand(10, 1), index=list(string.ascii_letters[:10]))
  538. axes = df.plot(subplots=True)
  539. self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  540. assert axes.shape == (1,)
  541. axes = df.plot(subplots=True, layout=(3, 3))
  542. self._check_axes_shape(axes, axes_num=1, layout=(3, 3))
  543. assert axes.shape == (3, 3)
  544. @pytest.mark.slow
  545. def test_subplots_warnings(self):
  546. # GH 9464
  547. with tm.assert_produces_warning(None):
  548. df = DataFrame(np.random.randn(100, 4))
  549. df.plot(subplots=True, layout=(3, 2))
  550. df = DataFrame(
  551. np.random.randn(100, 4), index=date_range("1/1/2000", periods=100)
  552. )
  553. df.plot(subplots=True, layout=(3, 2))
  554. @pytest.mark.slow
  555. def test_subplots_multiple_axes(self):
  556. # GH 5353, 6970, GH 7069
  557. fig, axes = self.plt.subplots(2, 3)
  558. df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10]))
  559. returned = df.plot(subplots=True, ax=axes[0], sharex=False, sharey=False)
  560. self._check_axes_shape(returned, axes_num=3, layout=(1, 3))
  561. assert returned.shape == (3,)
  562. assert returned[0].figure is fig
  563. # draw on second row
  564. returned = df.plot(subplots=True, ax=axes[1], sharex=False, sharey=False)
  565. self._check_axes_shape(returned, axes_num=3, layout=(1, 3))
  566. assert returned.shape == (3,)
  567. assert returned[0].figure is fig
  568. self._check_axes_shape(axes, axes_num=6, layout=(2, 3))
  569. tm.close()
  570. with pytest.raises(ValueError):
  571. fig, axes = self.plt.subplots(2, 3)
  572. # pass different number of axes from required
  573. df.plot(subplots=True, ax=axes)
  574. # pass 2-dim axes and invalid layout
  575. # invalid lauout should not affect to input and return value
  576. # (show warning is tested in
  577. # TestDataFrameGroupByPlots.test_grouped_box_multiple_axes
  578. fig, axes = self.plt.subplots(2, 2)
  579. with warnings.catch_warnings():
  580. warnings.simplefilter("ignore", UserWarning)
  581. df = DataFrame(np.random.rand(10, 4), index=list(string.ascii_letters[:10]))
  582. returned = df.plot(
  583. subplots=True, ax=axes, layout=(2, 1), sharex=False, sharey=False
  584. )
  585. self._check_axes_shape(returned, axes_num=4, layout=(2, 2))
  586. assert returned.shape == (4,)
  587. returned = df.plot(
  588. subplots=True, ax=axes, layout=(2, -1), sharex=False, sharey=False
  589. )
  590. self._check_axes_shape(returned, axes_num=4, layout=(2, 2))
  591. assert returned.shape == (4,)
  592. returned = df.plot(
  593. subplots=True, ax=axes, layout=(-1, 2), sharex=False, sharey=False
  594. )
  595. self._check_axes_shape(returned, axes_num=4, layout=(2, 2))
  596. assert returned.shape == (4,)
  597. # single column
  598. fig, axes = self.plt.subplots(1, 1)
  599. df = DataFrame(np.random.rand(10, 1), index=list(string.ascii_letters[:10]))
  600. axes = df.plot(subplots=True, ax=[axes], sharex=False, sharey=False)
  601. self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  602. assert axes.shape == (1,)
  603. def test_subplots_ts_share_axes(self):
  604. # GH 3964
  605. fig, axes = self.plt.subplots(3, 3, sharex=True, sharey=True)
  606. self.plt.subplots_adjust(left=0.05, right=0.95, hspace=0.3, wspace=0.3)
  607. df = DataFrame(
  608. np.random.randn(10, 9),
  609. index=date_range(start="2014-07-01", freq="M", periods=10),
  610. )
  611. for i, ax in enumerate(axes.ravel()):
  612. df[i].plot(ax=ax, fontsize=5)
  613. # Rows other than bottom should not be visible
  614. for ax in axes[0:-1].ravel():
  615. self._check_visible(ax.get_xticklabels(), visible=False)
  616. # Bottom row should be visible
  617. for ax in axes[-1].ravel():
  618. self._check_visible(ax.get_xticklabels(), visible=True)
  619. # First column should be visible
  620. for ax in axes[[0, 1, 2], [0]].ravel():
  621. self._check_visible(ax.get_yticklabels(), visible=True)
  622. # Other columns should not be visible
  623. for ax in axes[[0, 1, 2], [1]].ravel():
  624. self._check_visible(ax.get_yticklabels(), visible=False)
  625. for ax in axes[[0, 1, 2], [2]].ravel():
  626. self._check_visible(ax.get_yticklabels(), visible=False)
  627. def test_subplots_sharex_axes_existing_axes(self):
  628. # GH 9158
  629. d = {"A": [1.0, 2.0, 3.0, 4.0], "B": [4.0, 3.0, 2.0, 1.0], "C": [5, 1, 3, 4]}
  630. df = DataFrame(d, index=date_range("2014 10 11", "2014 10 14"))
  631. axes = df[["A", "B"]].plot(subplots=True)
  632. df["C"].plot(ax=axes[0], secondary_y=True)
  633. self._check_visible(axes[0].get_xticklabels(), visible=False)
  634. self._check_visible(axes[1].get_xticklabels(), visible=True)
  635. for ax in axes.ravel():
  636. self._check_visible(ax.get_yticklabels(), visible=True)
  637. @pytest.mark.slow
  638. def test_subplots_dup_columns(self):
  639. # GH 10962
  640. df = DataFrame(np.random.rand(5, 5), columns=list("aaaaa"))
  641. axes = df.plot(subplots=True)
  642. for ax in axes:
  643. self._check_legend_labels(ax, labels=["a"])
  644. assert len(ax.lines) == 1
  645. tm.close()
  646. axes = df.plot(subplots=True, secondary_y="a")
  647. for ax in axes:
  648. # (right) is only attached when subplots=False
  649. self._check_legend_labels(ax, labels=["a"])
  650. assert len(ax.lines) == 1
  651. tm.close()
  652. ax = df.plot(secondary_y="a")
  653. self._check_legend_labels(ax, labels=["a (right)"] * 5)
  654. assert len(ax.lines) == 0
  655. assert len(ax.right_ax.lines) == 5
  656. def test_negative_log(self):
  657. df = -DataFrame(
  658. rand(6, 4),
  659. index=list(string.ascii_letters[:6]),
  660. columns=["x", "y", "z", "four"],
  661. )
  662. with pytest.raises(ValueError):
  663. df.plot.area(logy=True)
  664. with pytest.raises(ValueError):
  665. df.plot.area(loglog=True)
  666. def _compare_stacked_y_cood(self, normal_lines, stacked_lines):
  667. base = np.zeros(len(normal_lines[0].get_data()[1]))
  668. for nl, sl in zip(normal_lines, stacked_lines):
  669. base += nl.get_data()[1] # get y coordinates
  670. sy = sl.get_data()[1]
  671. tm.assert_numpy_array_equal(base, sy)
  672. def test_line_area_stacked(self):
  673. with tm.RNGContext(42):
  674. df = DataFrame(rand(6, 4), columns=["w", "x", "y", "z"])
  675. neg_df = -df
  676. # each column has either positive or negative value
  677. sep_df = DataFrame(
  678. {"w": rand(6), "x": rand(6), "y": -rand(6), "z": -rand(6)}
  679. )
  680. # each column has positive-negative mixed value
  681. mixed_df = DataFrame(
  682. randn(6, 4),
  683. index=list(string.ascii_letters[:6]),
  684. columns=["w", "x", "y", "z"],
  685. )
  686. for kind in ["line", "area"]:
  687. ax1 = _check_plot_works(df.plot, kind=kind, stacked=False)
  688. ax2 = _check_plot_works(df.plot, kind=kind, stacked=True)
  689. self._compare_stacked_y_cood(ax1.lines, ax2.lines)
  690. ax1 = _check_plot_works(neg_df.plot, kind=kind, stacked=False)
  691. ax2 = _check_plot_works(neg_df.plot, kind=kind, stacked=True)
  692. self._compare_stacked_y_cood(ax1.lines, ax2.lines)
  693. ax1 = _check_plot_works(sep_df.plot, kind=kind, stacked=False)
  694. ax2 = _check_plot_works(sep_df.plot, kind=kind, stacked=True)
  695. self._compare_stacked_y_cood(ax1.lines[:2], ax2.lines[:2])
  696. self._compare_stacked_y_cood(ax1.lines[2:], ax2.lines[2:])
  697. _check_plot_works(mixed_df.plot, stacked=False)
  698. with pytest.raises(ValueError):
  699. mixed_df.plot(stacked=True)
  700. # Use an index with strictly positive values, preventing
  701. # matplotlib from warning about ignoring xlim
  702. df2 = df.set_index(df.index + 1)
  703. _check_plot_works(df2.plot, kind=kind, logx=True, stacked=True)
  704. def test_line_area_nan_df(self):
  705. values1 = [1, 2, np.nan, 3]
  706. values2 = [3, np.nan, 2, 1]
  707. df = DataFrame({"a": values1, "b": values2})
  708. tdf = DataFrame({"a": values1, "b": values2}, index=tm.makeDateIndex(k=4))
  709. for d in [df, tdf]:
  710. ax = _check_plot_works(d.plot)
  711. masked1 = ax.lines[0].get_ydata()
  712. masked2 = ax.lines[1].get_ydata()
  713. # remove nan for comparison purpose
  714. exp = np.array([1, 2, 3], dtype=np.float64)
  715. tm.assert_numpy_array_equal(np.delete(masked1.data, 2), exp)
  716. exp = np.array([3, 2, 1], dtype=np.float64)
  717. tm.assert_numpy_array_equal(np.delete(masked2.data, 1), exp)
  718. tm.assert_numpy_array_equal(
  719. masked1.mask, np.array([False, False, True, False])
  720. )
  721. tm.assert_numpy_array_equal(
  722. masked2.mask, np.array([False, True, False, False])
  723. )
  724. expected1 = np.array([1, 2, 0, 3], dtype=np.float64)
  725. expected2 = np.array([3, 0, 2, 1], dtype=np.float64)
  726. ax = _check_plot_works(d.plot, stacked=True)
  727. tm.assert_numpy_array_equal(ax.lines[0].get_ydata(), expected1)
  728. tm.assert_numpy_array_equal(ax.lines[1].get_ydata(), expected1 + expected2)
  729. ax = _check_plot_works(d.plot.area)
  730. tm.assert_numpy_array_equal(ax.lines[0].get_ydata(), expected1)
  731. tm.assert_numpy_array_equal(ax.lines[1].get_ydata(), expected1 + expected2)
  732. ax = _check_plot_works(d.plot.area, stacked=False)
  733. tm.assert_numpy_array_equal(ax.lines[0].get_ydata(), expected1)
  734. tm.assert_numpy_array_equal(ax.lines[1].get_ydata(), expected2)
  735. def test_line_lim(self):
  736. df = DataFrame(rand(6, 3), columns=["x", "y", "z"])
  737. ax = df.plot()
  738. xmin, xmax = ax.get_xlim()
  739. lines = ax.get_lines()
  740. assert xmin <= lines[0].get_data()[0][0]
  741. assert xmax >= lines[0].get_data()[0][-1]
  742. ax = df.plot(secondary_y=True)
  743. xmin, xmax = ax.get_xlim()
  744. lines = ax.get_lines()
  745. assert xmin <= lines[0].get_data()[0][0]
  746. assert xmax >= lines[0].get_data()[0][-1]
  747. axes = df.plot(secondary_y=True, subplots=True)
  748. self._check_axes_shape(axes, axes_num=3, layout=(3, 1))
  749. for ax in axes:
  750. assert hasattr(ax, "left_ax")
  751. assert not hasattr(ax, "right_ax")
  752. xmin, xmax = ax.get_xlim()
  753. lines = ax.get_lines()
  754. assert xmin <= lines[0].get_data()[0][0]
  755. assert xmax >= lines[0].get_data()[0][-1]
  756. def test_area_lim(self):
  757. df = DataFrame(rand(6, 4), columns=["x", "y", "z", "four"])
  758. neg_df = -df
  759. for stacked in [True, False]:
  760. ax = _check_plot_works(df.plot.area, stacked=stacked)
  761. xmin, xmax = ax.get_xlim()
  762. ymin, ymax = ax.get_ylim()
  763. lines = ax.get_lines()
  764. assert xmin <= lines[0].get_data()[0][0]
  765. assert xmax >= lines[0].get_data()[0][-1]
  766. assert ymin == 0
  767. ax = _check_plot_works(neg_df.plot.area, stacked=stacked)
  768. ymin, ymax = ax.get_ylim()
  769. assert ymax == 0
  770. @pytest.mark.slow
  771. def test_bar_colors(self):
  772. import matplotlib.pyplot as plt
  773. default_colors = self._unpack_cycler(plt.rcParams)
  774. df = DataFrame(randn(5, 5))
  775. ax = df.plot.bar()
  776. self._check_colors(ax.patches[::5], facecolors=default_colors[:5])
  777. tm.close()
  778. custom_colors = "rgcby"
  779. ax = df.plot.bar(color=custom_colors)
  780. self._check_colors(ax.patches[::5], facecolors=custom_colors)
  781. tm.close()
  782. from matplotlib import cm
  783. # Test str -> colormap functionality
  784. ax = df.plot.bar(colormap="jet")
  785. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)]
  786. self._check_colors(ax.patches[::5], facecolors=rgba_colors)
  787. tm.close()
  788. # Test colormap functionality
  789. ax = df.plot.bar(colormap=cm.jet)
  790. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)]
  791. self._check_colors(ax.patches[::5], facecolors=rgba_colors)
  792. tm.close()
  793. ax = df.loc[:, [0]].plot.bar(color="DodgerBlue")
  794. self._check_colors([ax.patches[0]], facecolors=["DodgerBlue"])
  795. tm.close()
  796. ax = df.plot(kind="bar", color="green")
  797. self._check_colors(ax.patches[::5], facecolors=["green"] * 5)
  798. tm.close()
  799. def test_bar_user_colors(self):
  800. df = pd.DataFrame(
  801. {"A": range(4), "B": range(1, 5), "color": ["red", "blue", "blue", "red"]}
  802. )
  803. # This should *only* work when `y` is specified, else
  804. # we use one color per column
  805. ax = df.plot.bar(y="A", color=df["color"])
  806. result = [p.get_facecolor() for p in ax.patches]
  807. expected = [
  808. (1.0, 0.0, 0.0, 1.0),
  809. (0.0, 0.0, 1.0, 1.0),
  810. (0.0, 0.0, 1.0, 1.0),
  811. (1.0, 0.0, 0.0, 1.0),
  812. ]
  813. assert result == expected
  814. @pytest.mark.slow
  815. def test_bar_linewidth(self):
  816. df = DataFrame(randn(5, 5))
  817. # regular
  818. ax = df.plot.bar(linewidth=2)
  819. for r in ax.patches:
  820. assert r.get_linewidth() == 2
  821. # stacked
  822. ax = df.plot.bar(stacked=True, linewidth=2)
  823. for r in ax.patches:
  824. assert r.get_linewidth() == 2
  825. # subplots
  826. axes = df.plot.bar(linewidth=2, subplots=True)
  827. self._check_axes_shape(axes, axes_num=5, layout=(5, 1))
  828. for ax in axes:
  829. for r in ax.patches:
  830. assert r.get_linewidth() == 2
  831. @pytest.mark.slow
  832. def test_bar_barwidth(self):
  833. df = DataFrame(randn(5, 5))
  834. width = 0.9
  835. # regular
  836. ax = df.plot.bar(width=width)
  837. for r in ax.patches:
  838. assert r.get_width() == width / len(df.columns)
  839. # stacked
  840. ax = df.plot.bar(stacked=True, width=width)
  841. for r in ax.patches:
  842. assert r.get_width() == width
  843. # horizontal regular
  844. ax = df.plot.barh(width=width)
  845. for r in ax.patches:
  846. assert r.get_height() == width / len(df.columns)
  847. # horizontal stacked
  848. ax = df.plot.barh(stacked=True, width=width)
  849. for r in ax.patches:
  850. assert r.get_height() == width
  851. # subplots
  852. axes = df.plot.bar(width=width, subplots=True)
  853. for ax in axes:
  854. for r in ax.patches:
  855. assert r.get_width() == width
  856. # horizontal subplots
  857. axes = df.plot.barh(width=width, subplots=True)
  858. for ax in axes:
  859. for r in ax.patches:
  860. assert r.get_height() == width
  861. @pytest.mark.slow
  862. def test_bar_barwidth_position(self):
  863. df = DataFrame(randn(5, 5))
  864. self._check_bar_alignment(
  865. df, kind="bar", stacked=False, width=0.9, position=0.2
  866. )
  867. self._check_bar_alignment(df, kind="bar", stacked=True, width=0.9, position=0.2)
  868. self._check_bar_alignment(
  869. df, kind="barh", stacked=False, width=0.9, position=0.2
  870. )
  871. self._check_bar_alignment(
  872. df, kind="barh", stacked=True, width=0.9, position=0.2
  873. )
  874. self._check_bar_alignment(
  875. df, kind="bar", subplots=True, width=0.9, position=0.2
  876. )
  877. self._check_bar_alignment(
  878. df, kind="barh", subplots=True, width=0.9, position=0.2
  879. )
  880. @pytest.mark.slow
  881. def test_bar_barwidth_position_int(self):
  882. # GH 12979
  883. df = DataFrame(randn(5, 5))
  884. for w in [1, 1.0]:
  885. ax = df.plot.bar(stacked=True, width=w)
  886. ticks = ax.xaxis.get_ticklocs()
  887. tm.assert_numpy_array_equal(ticks, np.array([0, 1, 2, 3, 4]))
  888. assert ax.get_xlim() == (-0.75, 4.75)
  889. # check left-edge of bars
  890. assert ax.patches[0].get_x() == -0.5
  891. assert ax.patches[-1].get_x() == 3.5
  892. self._check_bar_alignment(df, kind="bar", stacked=True, width=1)
  893. self._check_bar_alignment(df, kind="barh", stacked=False, width=1)
  894. self._check_bar_alignment(df, kind="barh", stacked=True, width=1)
  895. self._check_bar_alignment(df, kind="bar", subplots=True, width=1)
  896. self._check_bar_alignment(df, kind="barh", subplots=True, width=1)
  897. @pytest.mark.slow
  898. def test_bar_bottom_left(self):
  899. df = DataFrame(rand(5, 5))
  900. ax = df.plot.bar(stacked=False, bottom=1)
  901. result = [p.get_y() for p in ax.patches]
  902. assert result == [1] * 25
  903. ax = df.plot.bar(stacked=True, bottom=[-1, -2, -3, -4, -5])
  904. result = [p.get_y() for p in ax.patches[:5]]
  905. assert result == [-1, -2, -3, -4, -5]
  906. ax = df.plot.barh(stacked=False, left=np.array([1, 1, 1, 1, 1]))
  907. result = [p.get_x() for p in ax.patches]
  908. assert result == [1] * 25
  909. ax = df.plot.barh(stacked=True, left=[1, 2, 3, 4, 5])
  910. result = [p.get_x() for p in ax.patches[:5]]
  911. assert result == [1, 2, 3, 4, 5]
  912. axes = df.plot.bar(subplots=True, bottom=-1)
  913. for ax in axes:
  914. result = [p.get_y() for p in ax.patches]
  915. assert result == [-1] * 5
  916. axes = df.plot.barh(subplots=True, left=np.array([1, 1, 1, 1, 1]))
  917. for ax in axes:
  918. result = [p.get_x() for p in ax.patches]
  919. assert result == [1] * 5
  920. @pytest.mark.slow
  921. def test_bar_nan(self):
  922. df = DataFrame({"A": [10, np.nan, 20], "B": [5, 10, 20], "C": [1, 2, 3]})
  923. ax = df.plot.bar()
  924. expected = [10, 0, 20, 5, 10, 20, 1, 2, 3]
  925. result = [p.get_height() for p in ax.patches]
  926. assert result == expected
  927. ax = df.plot.bar(stacked=True)
  928. result = [p.get_height() for p in ax.patches]
  929. assert result == expected
  930. result = [p.get_y() for p in ax.patches]
  931. expected = [0.0, 0.0, 0.0, 10.0, 0.0, 20.0, 15.0, 10.0, 40.0]
  932. assert result == expected
  933. @pytest.mark.slow
  934. def test_bar_categorical(self):
  935. # GH 13019
  936. df1 = pd.DataFrame(
  937. np.random.randn(6, 5),
  938. index=pd.Index(list("ABCDEF")),
  939. columns=pd.Index(list("abcde")),
  940. )
  941. # categorical index must behave the same
  942. df2 = pd.DataFrame(
  943. np.random.randn(6, 5),
  944. index=pd.CategoricalIndex(list("ABCDEF")),
  945. columns=pd.CategoricalIndex(list("abcde")),
  946. )
  947. for df in [df1, df2]:
  948. ax = df.plot.bar()
  949. ticks = ax.xaxis.get_ticklocs()
  950. tm.assert_numpy_array_equal(ticks, np.array([0, 1, 2, 3, 4, 5]))
  951. assert ax.get_xlim() == (-0.5, 5.5)
  952. # check left-edge of bars
  953. assert ax.patches[0].get_x() == -0.25
  954. assert ax.patches[-1].get_x() == 5.15
  955. ax = df.plot.bar(stacked=True)
  956. tm.assert_numpy_array_equal(ticks, np.array([0, 1, 2, 3, 4, 5]))
  957. assert ax.get_xlim() == (-0.5, 5.5)
  958. assert ax.patches[0].get_x() == -0.25
  959. assert ax.patches[-1].get_x() == 4.75
  960. @pytest.mark.slow
  961. def test_plot_scatter(self):
  962. df = DataFrame(
  963. randn(6, 4),
  964. index=list(string.ascii_letters[:6]),
  965. columns=["x", "y", "z", "four"],
  966. )
  967. _check_plot_works(df.plot.scatter, x="x", y="y")
  968. _check_plot_works(df.plot.scatter, x=1, y=2)
  969. with pytest.raises(TypeError):
  970. df.plot.scatter(x="x")
  971. with pytest.raises(TypeError):
  972. df.plot.scatter(y="y")
  973. # GH 6951
  974. axes = df.plot(x="x", y="y", kind="scatter", subplots=True)
  975. self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  976. def test_raise_error_on_datetime_time_data(self):
  977. # GH 8113, datetime.time type is not supported by matplotlib in scatter
  978. df = pd.DataFrame(np.random.randn(10), columns=["a"])
  979. df["dtime"] = pd.date_range(start="2014-01-01", freq="h", periods=10).time
  980. msg = "must be a string or a number, not 'datetime.time'"
  981. with pytest.raises(TypeError, match=msg):
  982. df.plot(kind="scatter", x="dtime", y="a")
  983. def test_scatterplot_datetime_data(self):
  984. # GH 30391
  985. dates = pd.date_range(start=date(2019, 1, 1), periods=12, freq="W")
  986. vals = np.random.normal(0, 1, len(dates))
  987. df = pd.DataFrame({"dates": dates, "vals": vals})
  988. _check_plot_works(df.plot.scatter, x="dates", y="vals")
  989. _check_plot_works(df.plot.scatter, x=0, y=1)
  990. def test_scatterplot_object_data(self):
  991. # GH 18755
  992. df = pd.DataFrame(dict(a=["A", "B", "C"], b=[2, 3, 4]))
  993. _check_plot_works(df.plot.scatter, x="a", y="b")
  994. _check_plot_works(df.plot.scatter, x=0, y=1)
  995. df = pd.DataFrame(dict(a=["A", "B", "C"], b=["a", "b", "c"]))
  996. _check_plot_works(df.plot.scatter, x="a", y="b")
  997. _check_plot_works(df.plot.scatter, x=0, y=1)
  998. @pytest.mark.slow
  999. def test_if_scatterplot_colorbar_affects_xaxis_visibility(self):
  1000. # addressing issue #10611, to ensure colobar does not
  1001. # interfere with x-axis label and ticklabels with
  1002. # ipython inline backend.
  1003. random_array = np.random.random((1000, 3))
  1004. df = pd.DataFrame(random_array, columns=["A label", "B label", "C label"])
  1005. ax1 = df.plot.scatter(x="A label", y="B label")
  1006. ax2 = df.plot.scatter(x="A label", y="B label", c="C label")
  1007. vis1 = [vis.get_visible() for vis in ax1.xaxis.get_minorticklabels()]
  1008. vis2 = [vis.get_visible() for vis in ax2.xaxis.get_minorticklabels()]
  1009. assert vis1 == vis2
  1010. vis1 = [vis.get_visible() for vis in ax1.xaxis.get_majorticklabels()]
  1011. vis2 = [vis.get_visible() for vis in ax2.xaxis.get_majorticklabels()]
  1012. assert vis1 == vis2
  1013. assert (
  1014. ax1.xaxis.get_label().get_visible() == ax2.xaxis.get_label().get_visible()
  1015. )
  1016. @pytest.mark.slow
  1017. def test_if_hexbin_xaxis_label_is_visible(self):
  1018. # addressing issue #10678, to ensure colobar does not
  1019. # interfere with x-axis label and ticklabels with
  1020. # ipython inline backend.
  1021. random_array = np.random.random((1000, 3))
  1022. df = pd.DataFrame(random_array, columns=["A label", "B label", "C label"])
  1023. ax = df.plot.hexbin("A label", "B label", gridsize=12)
  1024. assert all(vis.get_visible() for vis in ax.xaxis.get_minorticklabels())
  1025. assert all(vis.get_visible() for vis in ax.xaxis.get_majorticklabels())
  1026. assert ax.xaxis.get_label().get_visible()
  1027. @pytest.mark.slow
  1028. def test_if_scatterplot_colorbars_are_next_to_parent_axes(self):
  1029. import matplotlib.pyplot as plt
  1030. random_array = np.random.random((1000, 3))
  1031. df = pd.DataFrame(random_array, columns=["A label", "B label", "C label"])
  1032. fig, axes = plt.subplots(1, 2)
  1033. df.plot.scatter("A label", "B label", c="C label", ax=axes[0])
  1034. df.plot.scatter("A label", "B label", c="C label", ax=axes[1])
  1035. plt.tight_layout()
  1036. points = np.array([ax.get_position().get_points() for ax in fig.axes])
  1037. axes_x_coords = points[:, :, 0]
  1038. parent_distance = axes_x_coords[1, :] - axes_x_coords[0, :]
  1039. colorbar_distance = axes_x_coords[3, :] - axes_x_coords[2, :]
  1040. assert np.isclose(parent_distance, colorbar_distance, atol=1e-7).all()
  1041. @pytest.mark.parametrize("x, y", [("x", "y"), ("y", "x"), ("y", "y")])
  1042. @pytest.mark.slow
  1043. def test_plot_scatter_with_categorical_data(self, x, y):
  1044. # after fixing GH 18755, should be able to plot categorical data
  1045. df = pd.DataFrame(
  1046. {"x": [1, 2, 3, 4], "y": pd.Categorical(["a", "b", "a", "c"])}
  1047. )
  1048. _check_plot_works(df.plot.scatter, x=x, y=y)
  1049. @pytest.mark.slow
  1050. def test_plot_scatter_with_c(self):
  1051. df = DataFrame(
  1052. randn(6, 4),
  1053. index=list(string.ascii_letters[:6]),
  1054. columns=["x", "y", "z", "four"],
  1055. )
  1056. axes = [df.plot.scatter(x="x", y="y", c="z"), df.plot.scatter(x=0, y=1, c=2)]
  1057. for ax in axes:
  1058. # default to Greys
  1059. assert ax.collections[0].cmap.name == "Greys"
  1060. # n.b. there appears to be no public method
  1061. # to get the colorbar label
  1062. assert ax.collections[0].colorbar._label == "z"
  1063. cm = "cubehelix"
  1064. ax = df.plot.scatter(x="x", y="y", c="z", colormap=cm)
  1065. assert ax.collections[0].cmap.name == cm
  1066. # verify turning off colorbar works
  1067. ax = df.plot.scatter(x="x", y="y", c="z", colorbar=False)
  1068. assert ax.collections[0].colorbar is None
  1069. # verify that we can still plot a solid color
  1070. ax = df.plot.scatter(x=0, y=1, c="red")
  1071. assert ax.collections[0].colorbar is None
  1072. self._check_colors(ax.collections, facecolors=["r"])
  1073. # Ensure that we can pass an np.array straight through to matplotlib,
  1074. # this functionality was accidentally removed previously.
  1075. # See https://github.com/pandas-dev/pandas/issues/8852 for bug report
  1076. #
  1077. # Exercise colormap path and non-colormap path as they are independent
  1078. #
  1079. df = DataFrame({"A": [1, 2], "B": [3, 4]})
  1080. red_rgba = [1.0, 0.0, 0.0, 1.0]
  1081. green_rgba = [0.0, 1.0, 0.0, 1.0]
  1082. rgba_array = np.array([red_rgba, green_rgba])
  1083. ax = df.plot.scatter(x="A", y="B", c=rgba_array)
  1084. # expect the face colors of the points in the non-colormap path to be
  1085. # identical to the values we supplied, normally we'd be on shaky ground
  1086. # comparing floats for equality but here we expect them to be
  1087. # identical.
  1088. tm.assert_numpy_array_equal(ax.collections[0].get_facecolor(), rgba_array)
  1089. # we don't test the colors of the faces in this next plot because they
  1090. # are dependent on the spring colormap, which may change its colors
  1091. # later.
  1092. float_array = np.array([0.0, 1.0])
  1093. df.plot.scatter(x="A", y="B", c=float_array, cmap="spring")
  1094. def test_scatter_colors(self):
  1095. df = DataFrame({"a": [1, 2, 3], "b": [1, 2, 3], "c": [1, 2, 3]})
  1096. with pytest.raises(TypeError):
  1097. df.plot.scatter(x="a", y="b", c="c", color="green")
  1098. default_colors = self._unpack_cycler(self.plt.rcParams)
  1099. ax = df.plot.scatter(x="a", y="b", c="c")
  1100. tm.assert_numpy_array_equal(
  1101. ax.collections[0].get_facecolor()[0],
  1102. np.array(self.colorconverter.to_rgba(default_colors[0])),
  1103. )
  1104. ax = df.plot.scatter(x="a", y="b", color="white")
  1105. tm.assert_numpy_array_equal(
  1106. ax.collections[0].get_facecolor()[0],
  1107. np.array([1, 1, 1, 1], dtype=np.float64),
  1108. )
  1109. @pytest.mark.slow
  1110. def test_plot_bar(self):
  1111. df = DataFrame(
  1112. randn(6, 4),
  1113. index=list(string.ascii_letters[:6]),
  1114. columns=["one", "two", "three", "four"],
  1115. )
  1116. _check_plot_works(df.plot.bar)
  1117. _check_plot_works(df.plot.bar, legend=False)
  1118. # _check_plot_works adds an ax so catch warning. see GH #13188
  1119. with tm.assert_produces_warning(UserWarning):
  1120. _check_plot_works(df.plot.bar, subplots=True)
  1121. _check_plot_works(df.plot.bar, stacked=True)
  1122. df = DataFrame(
  1123. randn(10, 15), index=list(string.ascii_letters[:10]), columns=range(15)
  1124. )
  1125. _check_plot_works(df.plot.bar)
  1126. df = DataFrame({"a": [0, 1], "b": [1, 0]})
  1127. ax = _check_plot_works(df.plot.bar)
  1128. self._check_ticks_props(ax, xrot=90)
  1129. ax = df.plot.bar(rot=35, fontsize=10)
  1130. self._check_ticks_props(ax, xrot=35, xlabelsize=10, ylabelsize=10)
  1131. ax = _check_plot_works(df.plot.barh)
  1132. self._check_ticks_props(ax, yrot=0)
  1133. ax = df.plot.barh(rot=55, fontsize=11)
  1134. self._check_ticks_props(ax, yrot=55, ylabelsize=11, xlabelsize=11)
  1135. def _check_bar_alignment(
  1136. self,
  1137. df,
  1138. kind="bar",
  1139. stacked=False,
  1140. subplots=False,
  1141. align="center",
  1142. width=0.5,
  1143. position=0.5,
  1144. ):
  1145. axes = df.plot(
  1146. kind=kind,
  1147. stacked=stacked,
  1148. subplots=subplots,
  1149. align=align,
  1150. width=width,
  1151. position=position,
  1152. grid=True,
  1153. )
  1154. axes = self._flatten_visible(axes)
  1155. for ax in axes:
  1156. if kind == "bar":
  1157. axis = ax.xaxis
  1158. ax_min, ax_max = ax.get_xlim()
  1159. min_edge = min(p.get_x() for p in ax.patches)
  1160. max_edge = max(p.get_x() + p.get_width() for p in ax.patches)
  1161. elif kind == "barh":
  1162. axis = ax.yaxis
  1163. ax_min, ax_max = ax.get_ylim()
  1164. min_edge = min(p.get_y() for p in ax.patches)
  1165. max_edge = max(p.get_y() + p.get_height() for p in ax.patches)
  1166. else:
  1167. raise ValueError
  1168. # GH 7498
  1169. # compare margins between lim and bar edges
  1170. tm.assert_almost_equal(ax_min, min_edge - 0.25)
  1171. tm.assert_almost_equal(ax_max, max_edge + 0.25)
  1172. p = ax.patches[0]
  1173. if kind == "bar" and (stacked is True or subplots is True):
  1174. edge = p.get_x()
  1175. center = edge + p.get_width() * position
  1176. elif kind == "bar" and stacked is False:
  1177. center = p.get_x() + p.get_width() * len(df.columns) * position
  1178. edge = p.get_x()
  1179. elif kind == "barh" and (stacked is True or subplots is True):
  1180. center = p.get_y() + p.get_height() * position
  1181. edge = p.get_y()
  1182. elif kind == "barh" and stacked is False:
  1183. center = p.get_y() + p.get_height() * len(df.columns) * position
  1184. edge = p.get_y()
  1185. else:
  1186. raise ValueError
  1187. # Check the ticks locates on integer
  1188. assert (axis.get_ticklocs() == np.arange(len(df))).all()
  1189. if align == "center":
  1190. # Check whether the bar locates on center
  1191. tm.assert_almost_equal(axis.get_ticklocs()[0], center)
  1192. elif align == "edge":
  1193. # Check whether the bar's edge starts from the tick
  1194. tm.assert_almost_equal(axis.get_ticklocs()[0], edge)
  1195. else:
  1196. raise ValueError
  1197. return axes
  1198. @pytest.mark.slow
  1199. def test_bar_stacked_center(self):
  1200. # GH2157
  1201. df = DataFrame({"A": [3] * 5, "B": list(range(5))}, index=range(5))
  1202. self._check_bar_alignment(df, kind="bar", stacked=True)
  1203. self._check_bar_alignment(df, kind="bar", stacked=True, width=0.9)
  1204. self._check_bar_alignment(df, kind="barh", stacked=True)
  1205. self._check_bar_alignment(df, kind="barh", stacked=True, width=0.9)
  1206. @pytest.mark.slow
  1207. def test_bar_center(self):
  1208. df = DataFrame({"A": [3] * 5, "B": list(range(5))}, index=range(5))
  1209. self._check_bar_alignment(df, kind="bar", stacked=False)
  1210. self._check_bar_alignment(df, kind="bar", stacked=False, width=0.9)
  1211. self._check_bar_alignment(df, kind="barh", stacked=False)
  1212. self._check_bar_alignment(df, kind="barh", stacked=False, width=0.9)
  1213. @pytest.mark.slow
  1214. def test_bar_subplots_center(self):
  1215. df = DataFrame({"A": [3] * 5, "B": list(range(5))}, index=range(5))
  1216. self._check_bar_alignment(df, kind="bar", subplots=True)
  1217. self._check_bar_alignment(df, kind="bar", subplots=True, width=0.9)
  1218. self._check_bar_alignment(df, kind="barh", subplots=True)
  1219. self._check_bar_alignment(df, kind="barh", subplots=True, width=0.9)
  1220. @pytest.mark.slow
  1221. def test_bar_align_single_column(self):
  1222. df = DataFrame(randn(5))
  1223. self._check_bar_alignment(df, kind="bar", stacked=False)
  1224. self._check_bar_alignment(df, kind="bar", stacked=True)
  1225. self._check_bar_alignment(df, kind="barh", stacked=False)
  1226. self._check_bar_alignment(df, kind="barh", stacked=True)
  1227. self._check_bar_alignment(df, kind="bar", subplots=True)
  1228. self._check_bar_alignment(df, kind="barh", subplots=True)
  1229. @pytest.mark.slow
  1230. def test_bar_edge(self):
  1231. df = DataFrame({"A": [3] * 5, "B": list(range(5))}, index=range(5))
  1232. self._check_bar_alignment(df, kind="bar", stacked=True, align="edge")
  1233. self._check_bar_alignment(df, kind="bar", stacked=True, width=0.9, align="edge")
  1234. self._check_bar_alignment(df, kind="barh", stacked=True, align="edge")
  1235. self._check_bar_alignment(
  1236. df, kind="barh", stacked=True, width=0.9, align="edge"
  1237. )
  1238. self._check_bar_alignment(df, kind="bar", stacked=False, align="edge")
  1239. self._check_bar_alignment(
  1240. df, kind="bar", stacked=False, width=0.9, align="edge"
  1241. )
  1242. self._check_bar_alignment(df, kind="barh", stacked=False, align="edge")
  1243. self._check_bar_alignment(
  1244. df, kind="barh", stacked=False, width=0.9, align="edge"
  1245. )
  1246. self._check_bar_alignment(df, kind="bar", subplots=True, align="edge")
  1247. self._check_bar_alignment(
  1248. df, kind="bar", subplots=True, width=0.9, align="edge"
  1249. )
  1250. self._check_bar_alignment(df, kind="barh", subplots=True, align="edge")
  1251. self._check_bar_alignment(
  1252. df, kind="barh", subplots=True, width=0.9, align="edge"
  1253. )
  1254. @pytest.mark.slow
  1255. def test_bar_log_no_subplots(self):
  1256. # GH3254, GH3298 matplotlib/matplotlib#1882, #1892
  1257. # regressions in 1.2.1
  1258. expected = np.array([0.1, 1.0, 10.0, 100])
  1259. # no subplots
  1260. df = DataFrame({"A": [3] * 5, "B": list(range(1, 6))}, index=range(5))
  1261. ax = df.plot.bar(grid=True, log=True)
  1262. tm.assert_numpy_array_equal(ax.yaxis.get_ticklocs(), expected)
  1263. @pytest.mark.slow
  1264. def test_bar_log_subplots(self):
  1265. expected = np.array([0.1, 1.0, 10.0, 100.0, 1000.0, 1e4])
  1266. ax = DataFrame([Series([200, 300]), Series([300, 500])]).plot.bar(
  1267. log=True, subplots=True
  1268. )
  1269. tm.assert_numpy_array_equal(ax[0].yaxis.get_ticklocs(), expected)
  1270. tm.assert_numpy_array_equal(ax[1].yaxis.get_ticklocs(), expected)
  1271. @pytest.mark.slow
  1272. def test_boxplot(self):
  1273. df = self.hist_df
  1274. series = df["height"]
  1275. numeric_cols = df._get_numeric_data().columns
  1276. labels = [pprint_thing(c) for c in numeric_cols]
  1277. ax = _check_plot_works(df.plot.box)
  1278. self._check_text_labels(ax.get_xticklabels(), labels)
  1279. tm.assert_numpy_array_equal(
  1280. ax.xaxis.get_ticklocs(), np.arange(1, len(numeric_cols) + 1)
  1281. )
  1282. assert len(ax.lines) == self.bp_n_objects * len(numeric_cols)
  1283. axes = series.plot.box(rot=40)
  1284. self._check_ticks_props(axes, xrot=40, yrot=0)
  1285. tm.close()
  1286. ax = _check_plot_works(series.plot.box)
  1287. positions = np.array([1, 6, 7])
  1288. ax = df.plot.box(positions=positions)
  1289. numeric_cols = df._get_numeric_data().columns
  1290. labels = [pprint_thing(c) for c in numeric_cols]
  1291. self._check_text_labels(ax.get_xticklabels(), labels)
  1292. tm.assert_numpy_array_equal(ax.xaxis.get_ticklocs(), positions)
  1293. assert len(ax.lines) == self.bp_n_objects * len(numeric_cols)
  1294. @pytest.mark.slow
  1295. def test_boxplot_vertical(self):
  1296. df = self.hist_df
  1297. numeric_cols = df._get_numeric_data().columns
  1298. labels = [pprint_thing(c) for c in numeric_cols]
  1299. # if horizontal, yticklabels are rotated
  1300. ax = df.plot.box(rot=50, fontsize=8, vert=False)
  1301. self._check_ticks_props(ax, xrot=0, yrot=50, ylabelsize=8)
  1302. self._check_text_labels(ax.get_yticklabels(), labels)
  1303. assert len(ax.lines) == self.bp_n_objects * len(numeric_cols)
  1304. # _check_plot_works adds an ax so catch warning. see GH #13188
  1305. with tm.assert_produces_warning(UserWarning):
  1306. axes = _check_plot_works(df.plot.box, subplots=True, vert=False, logx=True)
  1307. self._check_axes_shape(axes, axes_num=3, layout=(1, 3))
  1308. self._check_ax_scales(axes, xaxis="log")
  1309. for ax, label in zip(axes, labels):
  1310. self._check_text_labels(ax.get_yticklabels(), [label])
  1311. assert len(ax.lines) == self.bp_n_objects
  1312. positions = np.array([3, 2, 8])
  1313. ax = df.plot.box(positions=positions, vert=False)
  1314. self._check_text_labels(ax.get_yticklabels(), labels)
  1315. tm.assert_numpy_array_equal(ax.yaxis.get_ticklocs(), positions)
  1316. assert len(ax.lines) == self.bp_n_objects * len(numeric_cols)
  1317. @pytest.mark.slow
  1318. def test_boxplot_return_type(self):
  1319. df = DataFrame(
  1320. randn(6, 4),
  1321. index=list(string.ascii_letters[:6]),
  1322. columns=["one", "two", "three", "four"],
  1323. )
  1324. with pytest.raises(ValueError):
  1325. df.plot.box(return_type="NOTATYPE")
  1326. result = df.plot.box(return_type="dict")
  1327. self._check_box_return_type(result, "dict")
  1328. result = df.plot.box(return_type="axes")
  1329. self._check_box_return_type(result, "axes")
  1330. result = df.plot.box() # default axes
  1331. self._check_box_return_type(result, "axes")
  1332. result = df.plot.box(return_type="both")
  1333. self._check_box_return_type(result, "both")
  1334. @pytest.mark.slow
  1335. def test_boxplot_subplots_return_type(self):
  1336. df = self.hist_df
  1337. # normal style: return_type=None
  1338. result = df.plot.box(subplots=True)
  1339. assert isinstance(result, Series)
  1340. self._check_box_return_type(
  1341. result, None, expected_keys=["height", "weight", "category"]
  1342. )
  1343. for t in ["dict", "axes", "both"]:
  1344. returned = df.plot.box(return_type=t, subplots=True)
  1345. self._check_box_return_type(
  1346. returned,
  1347. t,
  1348. expected_keys=["height", "weight", "category"],
  1349. check_ax_title=False,
  1350. )
  1351. @pytest.mark.slow
  1352. @td.skip_if_no_scipy
  1353. def test_kde_df(self):
  1354. df = DataFrame(randn(100, 4))
  1355. ax = _check_plot_works(df.plot, kind="kde")
  1356. expected = [pprint_thing(c) for c in df.columns]
  1357. self._check_legend_labels(ax, labels=expected)
  1358. self._check_ticks_props(ax, xrot=0)
  1359. ax = df.plot(kind="kde", rot=20, fontsize=5)
  1360. self._check_ticks_props(ax, xrot=20, xlabelsize=5, ylabelsize=5)
  1361. with tm.assert_produces_warning(UserWarning):
  1362. axes = _check_plot_works(df.plot, kind="kde", subplots=True)
  1363. self._check_axes_shape(axes, axes_num=4, layout=(4, 1))
  1364. axes = df.plot(kind="kde", logy=True, subplots=True)
  1365. self._check_ax_scales(axes, yaxis="log")
  1366. @pytest.mark.slow
  1367. @td.skip_if_no_scipy
  1368. def test_kde_missing_vals(self):
  1369. df = DataFrame(np.random.uniform(size=(100, 4)))
  1370. df.loc[0, 0] = np.nan
  1371. _check_plot_works(df.plot, kind="kde")
  1372. @pytest.mark.slow
  1373. def test_hist_df(self):
  1374. from matplotlib.patches import Rectangle
  1375. df = DataFrame(randn(100, 4))
  1376. series = df[0]
  1377. ax = _check_plot_works(df.plot.hist)
  1378. expected = [pprint_thing(c) for c in df.columns]
  1379. self._check_legend_labels(ax, labels=expected)
  1380. with tm.assert_produces_warning(UserWarning):
  1381. axes = _check_plot_works(df.plot.hist, subplots=True, logy=True)
  1382. self._check_axes_shape(axes, axes_num=4, layout=(4, 1))
  1383. self._check_ax_scales(axes, yaxis="log")
  1384. axes = series.plot.hist(rot=40)
  1385. self._check_ticks_props(axes, xrot=40, yrot=0)
  1386. tm.close()
  1387. ax = series.plot.hist(cumulative=True, bins=4, density=True)
  1388. # height of last bin (index 5) must be 1.0
  1389. rects = [x for x in ax.get_children() if isinstance(x, Rectangle)]
  1390. tm.assert_almost_equal(rects[-1].get_height(), 1.0)
  1391. tm.close()
  1392. ax = series.plot.hist(cumulative=True, bins=4)
  1393. rects = [x for x in ax.get_children() if isinstance(x, Rectangle)]
  1394. tm.assert_almost_equal(rects[-2].get_height(), 100.0)
  1395. tm.close()
  1396. # if horizontal, yticklabels are rotated
  1397. axes = df.plot.hist(rot=50, fontsize=8, orientation="horizontal")
  1398. self._check_ticks_props(axes, xrot=0, yrot=50, ylabelsize=8)
  1399. def _check_box_coord(
  1400. self,
  1401. patches,
  1402. expected_y=None,
  1403. expected_h=None,
  1404. expected_x=None,
  1405. expected_w=None,
  1406. ):
  1407. result_y = np.array([p.get_y() for p in patches])
  1408. result_height = np.array([p.get_height() for p in patches])
  1409. result_x = np.array([p.get_x() for p in patches])
  1410. result_width = np.array([p.get_width() for p in patches])
  1411. # dtype is depending on above values, no need to check
  1412. if expected_y is not None:
  1413. tm.assert_numpy_array_equal(result_y, expected_y, check_dtype=False)
  1414. if expected_h is not None:
  1415. tm.assert_numpy_array_equal(result_height, expected_h, check_dtype=False)
  1416. if expected_x is not None:
  1417. tm.assert_numpy_array_equal(result_x, expected_x, check_dtype=False)
  1418. if expected_w is not None:
  1419. tm.assert_numpy_array_equal(result_width, expected_w, check_dtype=False)
  1420. @pytest.mark.slow
  1421. def test_hist_df_coord(self):
  1422. normal_df = DataFrame(
  1423. {
  1424. "A": np.repeat(np.array([1, 2, 3, 4, 5]), np.array([10, 9, 8, 7, 6])),
  1425. "B": np.repeat(np.array([1, 2, 3, 4, 5]), np.array([8, 8, 8, 8, 8])),
  1426. "C": np.repeat(np.array([1, 2, 3, 4, 5]), np.array([6, 7, 8, 9, 10])),
  1427. },
  1428. columns=["A", "B", "C"],
  1429. )
  1430. nan_df = DataFrame(
  1431. {
  1432. "A": np.repeat(
  1433. np.array([np.nan, 1, 2, 3, 4, 5]), np.array([3, 10, 9, 8, 7, 6])
  1434. ),
  1435. "B": np.repeat(
  1436. np.array([1, np.nan, 2, 3, 4, 5]), np.array([8, 3, 8, 8, 8, 8])
  1437. ),
  1438. "C": np.repeat(
  1439. np.array([1, 2, 3, np.nan, 4, 5]), np.array([6, 7, 8, 3, 9, 10])
  1440. ),
  1441. },
  1442. columns=["A", "B", "C"],
  1443. )
  1444. for df in [normal_df, nan_df]:
  1445. ax = df.plot.hist(bins=5)
  1446. self._check_box_coord(
  1447. ax.patches[:5],
  1448. expected_y=np.array([0, 0, 0, 0, 0]),
  1449. expected_h=np.array([10, 9, 8, 7, 6]),
  1450. )
  1451. self._check_box_coord(
  1452. ax.patches[5:10],
  1453. expected_y=np.array([0, 0, 0, 0, 0]),
  1454. expected_h=np.array([8, 8, 8, 8, 8]),
  1455. )
  1456. self._check_box_coord(
  1457. ax.patches[10:],
  1458. expected_y=np.array([0, 0, 0, 0, 0]),
  1459. expected_h=np.array([6, 7, 8, 9, 10]),
  1460. )
  1461. ax = df.plot.hist(bins=5, stacked=True)
  1462. self._check_box_coord(
  1463. ax.patches[:5],
  1464. expected_y=np.array([0, 0, 0, 0, 0]),
  1465. expected_h=np.array([10, 9, 8, 7, 6]),
  1466. )
  1467. self._check_box_coord(
  1468. ax.patches[5:10],
  1469. expected_y=np.array([10, 9, 8, 7, 6]),
  1470. expected_h=np.array([8, 8, 8, 8, 8]),
  1471. )
  1472. self._check_box_coord(
  1473. ax.patches[10:],
  1474. expected_y=np.array([18, 17, 16, 15, 14]),
  1475. expected_h=np.array([6, 7, 8, 9, 10]),
  1476. )
  1477. axes = df.plot.hist(bins=5, stacked=True, subplots=True)
  1478. self._check_box_coord(
  1479. axes[0].patches,
  1480. expected_y=np.array([0, 0, 0, 0, 0]),
  1481. expected_h=np.array([10, 9, 8, 7, 6]),
  1482. )
  1483. self._check_box_coord(
  1484. axes[1].patches,
  1485. expected_y=np.array([0, 0, 0, 0, 0]),
  1486. expected_h=np.array([8, 8, 8, 8, 8]),
  1487. )
  1488. self._check_box_coord(
  1489. axes[2].patches,
  1490. expected_y=np.array([0, 0, 0, 0, 0]),
  1491. expected_h=np.array([6, 7, 8, 9, 10]),
  1492. )
  1493. # horizontal
  1494. ax = df.plot.hist(bins=5, orientation="horizontal")
  1495. self._check_box_coord(
  1496. ax.patches[:5],
  1497. expected_x=np.array([0, 0, 0, 0, 0]),
  1498. expected_w=np.array([10, 9, 8, 7, 6]),
  1499. )
  1500. self._check_box_coord(
  1501. ax.patches[5:10],
  1502. expected_x=np.array([0, 0, 0, 0, 0]),
  1503. expected_w=np.array([8, 8, 8, 8, 8]),
  1504. )
  1505. self._check_box_coord(
  1506. ax.patches[10:],
  1507. expected_x=np.array([0, 0, 0, 0, 0]),
  1508. expected_w=np.array([6, 7, 8, 9, 10]),
  1509. )
  1510. ax = df.plot.hist(bins=5, stacked=True, orientation="horizontal")
  1511. self._check_box_coord(
  1512. ax.patches[:5],
  1513. expected_x=np.array([0, 0, 0, 0, 0]),
  1514. expected_w=np.array([10, 9, 8, 7, 6]),
  1515. )
  1516. self._check_box_coord(
  1517. ax.patches[5:10],
  1518. expected_x=np.array([10, 9, 8, 7, 6]),
  1519. expected_w=np.array([8, 8, 8, 8, 8]),
  1520. )
  1521. self._check_box_coord(
  1522. ax.patches[10:],
  1523. expected_x=np.array([18, 17, 16, 15, 14]),
  1524. expected_w=np.array([6, 7, 8, 9, 10]),
  1525. )
  1526. axes = df.plot.hist(
  1527. bins=5, stacked=True, subplots=True, orientation="horizontal"
  1528. )
  1529. self._check_box_coord(
  1530. axes[0].patches,
  1531. expected_x=np.array([0, 0, 0, 0, 0]),
  1532. expected_w=np.array([10, 9, 8, 7, 6]),
  1533. )
  1534. self._check_box_coord(
  1535. axes[1].patches,
  1536. expected_x=np.array([0, 0, 0, 0, 0]),
  1537. expected_w=np.array([8, 8, 8, 8, 8]),
  1538. )
  1539. self._check_box_coord(
  1540. axes[2].patches,
  1541. expected_x=np.array([0, 0, 0, 0, 0]),
  1542. expected_w=np.array([6, 7, 8, 9, 10]),
  1543. )
  1544. @pytest.mark.slow
  1545. def test_plot_int_columns(self):
  1546. df = DataFrame(randn(100, 4)).cumsum()
  1547. _check_plot_works(df.plot, legend=True)
  1548. @pytest.mark.slow
  1549. def test_df_legend_labels(self):
  1550. kinds = ["line", "bar", "barh", "kde", "area", "hist"]
  1551. df = DataFrame(rand(3, 3), columns=["a", "b", "c"])
  1552. df2 = DataFrame(rand(3, 3), columns=["d", "e", "f"])
  1553. df3 = DataFrame(rand(3, 3), columns=["g", "h", "i"])
  1554. df4 = DataFrame(rand(3, 3), columns=["j", "k", "l"])
  1555. for kind in kinds:
  1556. ax = df.plot(kind=kind, legend=True)
  1557. self._check_legend_labels(ax, labels=df.columns)
  1558. ax = df2.plot(kind=kind, legend=False, ax=ax)
  1559. self._check_legend_labels(ax, labels=df.columns)
  1560. ax = df3.plot(kind=kind, legend=True, ax=ax)
  1561. self._check_legend_labels(ax, labels=df.columns.union(df3.columns))
  1562. ax = df4.plot(kind=kind, legend="reverse", ax=ax)
  1563. expected = list(df.columns.union(df3.columns)) + list(reversed(df4.columns))
  1564. self._check_legend_labels(ax, labels=expected)
  1565. # Secondary Y
  1566. ax = df.plot(legend=True, secondary_y="b")
  1567. self._check_legend_labels(ax, labels=["a", "b (right)", "c"])
  1568. ax = df2.plot(legend=False, ax=ax)
  1569. self._check_legend_labels(ax, labels=["a", "b (right)", "c"])
  1570. ax = df3.plot(kind="bar", legend=True, secondary_y="h", ax=ax)
  1571. self._check_legend_labels(
  1572. ax, labels=["a", "b (right)", "c", "g", "h (right)", "i"]
  1573. )
  1574. # Time Series
  1575. ind = date_range("1/1/2014", periods=3)
  1576. df = DataFrame(randn(3, 3), columns=["a", "b", "c"], index=ind)
  1577. df2 = DataFrame(randn(3, 3), columns=["d", "e", "f"], index=ind)
  1578. df3 = DataFrame(randn(3, 3), columns=["g", "h", "i"], index=ind)
  1579. ax = df.plot(legend=True, secondary_y="b")
  1580. self._check_legend_labels(ax, labels=["a", "b (right)", "c"])
  1581. ax = df2.plot(legend=False, ax=ax)
  1582. self._check_legend_labels(ax, labels=["a", "b (right)", "c"])
  1583. ax = df3.plot(legend=True, ax=ax)
  1584. self._check_legend_labels(ax, labels=["a", "b (right)", "c", "g", "h", "i"])
  1585. # scatter
  1586. ax = df.plot.scatter(x="a", y="b", label="data1")
  1587. self._check_legend_labels(ax, labels=["data1"])
  1588. ax = df2.plot.scatter(x="d", y="e", legend=False, label="data2", ax=ax)
  1589. self._check_legend_labels(ax, labels=["data1"])
  1590. ax = df3.plot.scatter(x="g", y="h", label="data3", ax=ax)
  1591. self._check_legend_labels(ax, labels=["data1", "data3"])
  1592. # ensure label args pass through and
  1593. # index name does not mutate
  1594. # column names don't mutate
  1595. df5 = df.set_index("a")
  1596. ax = df5.plot(y="b")
  1597. self._check_legend_labels(ax, labels=["b"])
  1598. ax = df5.plot(y="b", label="LABEL_b")
  1599. self._check_legend_labels(ax, labels=["LABEL_b"])
  1600. self._check_text_labels(ax.xaxis.get_label(), "a")
  1601. ax = df5.plot(y="c", label="LABEL_c", ax=ax)
  1602. self._check_legend_labels(ax, labels=["LABEL_b", "LABEL_c"])
  1603. assert df5.columns.tolist() == ["b", "c"]
  1604. def test_missing_marker_multi_plots_on_same_ax(self):
  1605. # GH 18222
  1606. df = pd.DataFrame(
  1607. data=[[1, 1, 1, 1], [2, 2, 4, 8]], columns=["x", "r", "g", "b"]
  1608. )
  1609. fig, ax = self.plt.subplots(nrows=1, ncols=3)
  1610. # Left plot
  1611. df.plot(x="x", y="r", linewidth=0, marker="o", color="r", ax=ax[0])
  1612. df.plot(x="x", y="g", linewidth=1, marker="x", color="g", ax=ax[0])
  1613. df.plot(x="x", y="b", linewidth=1, marker="o", color="b", ax=ax[0])
  1614. self._check_legend_labels(ax[0], labels=["r", "g", "b"])
  1615. self._check_legend_marker(ax[0], expected_markers=["o", "x", "o"])
  1616. # Center plot
  1617. df.plot(x="x", y="b", linewidth=1, marker="o", color="b", ax=ax[1])
  1618. df.plot(x="x", y="r", linewidth=0, marker="o", color="r", ax=ax[1])
  1619. df.plot(x="x", y="g", linewidth=1, marker="x", color="g", ax=ax[1])
  1620. self._check_legend_labels(ax[1], labels=["b", "r", "g"])
  1621. self._check_legend_marker(ax[1], expected_markers=["o", "o", "x"])
  1622. # Right plot
  1623. df.plot(x="x", y="g", linewidth=1, marker="x", color="g", ax=ax[2])
  1624. df.plot(x="x", y="b", linewidth=1, marker="o", color="b", ax=ax[2])
  1625. df.plot(x="x", y="r", linewidth=0, marker="o", color="r", ax=ax[2])
  1626. self._check_legend_labels(ax[2], labels=["g", "b", "r"])
  1627. self._check_legend_marker(ax[2], expected_markers=["x", "o", "o"])
  1628. def test_legend_name(self):
  1629. multi = DataFrame(
  1630. randn(4, 4),
  1631. columns=[np.array(["a", "a", "b", "b"]), np.array(["x", "y", "x", "y"])],
  1632. )
  1633. multi.columns.names = ["group", "individual"]
  1634. ax = multi.plot()
  1635. leg_title = ax.legend_.get_title()
  1636. self._check_text_labels(leg_title, "group,individual")
  1637. df = DataFrame(randn(5, 5))
  1638. ax = df.plot(legend=True, ax=ax)
  1639. leg_title = ax.legend_.get_title()
  1640. self._check_text_labels(leg_title, "group,individual")
  1641. df.columns.name = "new"
  1642. ax = df.plot(legend=False, ax=ax)
  1643. leg_title = ax.legend_.get_title()
  1644. self._check_text_labels(leg_title, "group,individual")
  1645. ax = df.plot(legend=True, ax=ax)
  1646. leg_title = ax.legend_.get_title()
  1647. self._check_text_labels(leg_title, "new")
  1648. @pytest.mark.slow
  1649. def test_no_legend(self):
  1650. kinds = ["line", "bar", "barh", "kde", "area", "hist"]
  1651. df = DataFrame(rand(3, 3), columns=["a", "b", "c"])
  1652. for kind in kinds:
  1653. ax = df.plot(kind=kind, legend=False)
  1654. self._check_legend_labels(ax, visible=False)
  1655. @pytest.mark.slow
  1656. def test_style_by_column(self):
  1657. import matplotlib.pyplot as plt
  1658. fig = plt.gcf()
  1659. df = DataFrame(randn(100, 3))
  1660. for markers in [
  1661. {0: "^", 1: "+", 2: "o"},
  1662. {0: "^", 1: "+"},
  1663. ["^", "+", "o"],
  1664. ["^", "+"],
  1665. ]:
  1666. fig.clf()
  1667. fig.add_subplot(111)
  1668. ax = df.plot(style=markers)
  1669. for i, l in enumerate(ax.get_lines()[: len(markers)]):
  1670. assert l.get_marker() == markers[i]
  1671. @pytest.mark.slow
  1672. def test_line_label_none(self):
  1673. s = Series([1, 2])
  1674. ax = s.plot()
  1675. assert ax.get_legend() is None
  1676. ax = s.plot(legend=True)
  1677. assert ax.get_legend().get_texts()[0].get_text() == "None"
  1678. @pytest.mark.slow
  1679. def test_line_colors(self):
  1680. from matplotlib import cm
  1681. custom_colors = "rgcby"
  1682. df = DataFrame(randn(5, 5))
  1683. ax = df.plot(color=custom_colors)
  1684. self._check_colors(ax.get_lines(), linecolors=custom_colors)
  1685. tm.close()
  1686. ax2 = df.plot(color=custom_colors)
  1687. lines2 = ax2.get_lines()
  1688. for l1, l2 in zip(ax.get_lines(), lines2):
  1689. assert l1.get_color() == l2.get_color()
  1690. tm.close()
  1691. ax = df.plot(colormap="jet")
  1692. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))]
  1693. self._check_colors(ax.get_lines(), linecolors=rgba_colors)
  1694. tm.close()
  1695. ax = df.plot(colormap=cm.jet)
  1696. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))]
  1697. self._check_colors(ax.get_lines(), linecolors=rgba_colors)
  1698. tm.close()
  1699. # make color a list if plotting one column frame
  1700. # handles cases like df.plot(color='DodgerBlue')
  1701. ax = df.loc[:, [0]].plot(color="DodgerBlue")
  1702. self._check_colors(ax.lines, linecolors=["DodgerBlue"])
  1703. ax = df.plot(color="red")
  1704. self._check_colors(ax.get_lines(), linecolors=["red"] * 5)
  1705. tm.close()
  1706. # GH 10299
  1707. custom_colors = ["#FF0000", "#0000FF", "#FFFF00", "#000000", "#FFFFFF"]
  1708. ax = df.plot(color=custom_colors)
  1709. self._check_colors(ax.get_lines(), linecolors=custom_colors)
  1710. tm.close()
  1711. with pytest.raises(ValueError):
  1712. # Color contains shorthand hex value results in ValueError
  1713. custom_colors = ["#F00", "#00F", "#FF0", "#000", "#FFF"]
  1714. # Forced show plot
  1715. _check_plot_works(df.plot, color=custom_colors)
  1716. @pytest.mark.slow
  1717. def test_dont_modify_colors(self):
  1718. colors = ["r", "g", "b"]
  1719. pd.DataFrame(np.random.rand(10, 2)).plot(color=colors)
  1720. assert len(colors) == 3
  1721. @pytest.mark.slow
  1722. def test_line_colors_and_styles_subplots(self):
  1723. # GH 9894
  1724. from matplotlib import cm
  1725. default_colors = self._unpack_cycler(self.plt.rcParams)
  1726. df = DataFrame(randn(5, 5))
  1727. axes = df.plot(subplots=True)
  1728. for ax, c in zip(axes, list(default_colors)):
  1729. c = [c]
  1730. self._check_colors(ax.get_lines(), linecolors=c)
  1731. tm.close()
  1732. # single color char
  1733. axes = df.plot(subplots=True, color="k")
  1734. for ax in axes:
  1735. self._check_colors(ax.get_lines(), linecolors=["k"])
  1736. tm.close()
  1737. # single color str
  1738. axes = df.plot(subplots=True, color="green")
  1739. for ax in axes:
  1740. self._check_colors(ax.get_lines(), linecolors=["green"])
  1741. tm.close()
  1742. custom_colors = "rgcby"
  1743. axes = df.plot(color=custom_colors, subplots=True)
  1744. for ax, c in zip(axes, list(custom_colors)):
  1745. self._check_colors(ax.get_lines(), linecolors=[c])
  1746. tm.close()
  1747. axes = df.plot(color=list(custom_colors), subplots=True)
  1748. for ax, c in zip(axes, list(custom_colors)):
  1749. self._check_colors(ax.get_lines(), linecolors=[c])
  1750. tm.close()
  1751. # GH 10299
  1752. custom_colors = ["#FF0000", "#0000FF", "#FFFF00", "#000000", "#FFFFFF"]
  1753. axes = df.plot(color=custom_colors, subplots=True)
  1754. for ax, c in zip(axes, list(custom_colors)):
  1755. self._check_colors(ax.get_lines(), linecolors=[c])
  1756. tm.close()
  1757. with pytest.raises(ValueError):
  1758. # Color contains shorthand hex value results in ValueError
  1759. custom_colors = ["#F00", "#00F", "#FF0", "#000", "#FFF"]
  1760. # Forced show plot
  1761. # _check_plot_works adds an ax so catch warning. see GH #13188
  1762. with tm.assert_produces_warning(UserWarning):
  1763. _check_plot_works(df.plot, color=custom_colors, subplots=True)
  1764. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))]
  1765. for cmap in ["jet", cm.jet]:
  1766. axes = df.plot(colormap=cmap, subplots=True)
  1767. for ax, c in zip(axes, rgba_colors):
  1768. self._check_colors(ax.get_lines(), linecolors=[c])
  1769. tm.close()
  1770. # make color a list if plotting one column frame
  1771. # handles cases like df.plot(color='DodgerBlue')
  1772. axes = df.loc[:, [0]].plot(color="DodgerBlue", subplots=True)
  1773. self._check_colors(axes[0].lines, linecolors=["DodgerBlue"])
  1774. # single character style
  1775. axes = df.plot(style="r", subplots=True)
  1776. for ax in axes:
  1777. self._check_colors(ax.get_lines(), linecolors=["r"])
  1778. tm.close()
  1779. # list of styles
  1780. styles = list("rgcby")
  1781. axes = df.plot(style=styles, subplots=True)
  1782. for ax, c in zip(axes, styles):
  1783. self._check_colors(ax.get_lines(), linecolors=[c])
  1784. tm.close()
  1785. @pytest.mark.slow
  1786. def test_area_colors(self):
  1787. from matplotlib import cm
  1788. from matplotlib.collections import PolyCollection
  1789. custom_colors = "rgcby"
  1790. df = DataFrame(rand(5, 5))
  1791. ax = df.plot.area(color=custom_colors)
  1792. self._check_colors(ax.get_lines(), linecolors=custom_colors)
  1793. poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)]
  1794. self._check_colors(poly, facecolors=custom_colors)
  1795. handles, labels = ax.get_legend_handles_labels()
  1796. self._check_colors(handles, facecolors=custom_colors)
  1797. for h in handles:
  1798. assert h.get_alpha() is None
  1799. tm.close()
  1800. ax = df.plot.area(colormap="jet")
  1801. jet_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))]
  1802. self._check_colors(ax.get_lines(), linecolors=jet_colors)
  1803. poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)]
  1804. self._check_colors(poly, facecolors=jet_colors)
  1805. handles, labels = ax.get_legend_handles_labels()
  1806. self._check_colors(handles, facecolors=jet_colors)
  1807. for h in handles:
  1808. assert h.get_alpha() is None
  1809. tm.close()
  1810. # When stacked=False, alpha is set to 0.5
  1811. ax = df.plot.area(colormap=cm.jet, stacked=False)
  1812. self._check_colors(ax.get_lines(), linecolors=jet_colors)
  1813. poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)]
  1814. jet_with_alpha = [(c[0], c[1], c[2], 0.5) for c in jet_colors]
  1815. self._check_colors(poly, facecolors=jet_with_alpha)
  1816. handles, labels = ax.get_legend_handles_labels()
  1817. linecolors = jet_with_alpha
  1818. self._check_colors(handles[: len(jet_colors)], linecolors=linecolors)
  1819. for h in handles:
  1820. assert h.get_alpha() == 0.5
  1821. @pytest.mark.slow
  1822. def test_hist_colors(self):
  1823. default_colors = self._unpack_cycler(self.plt.rcParams)
  1824. df = DataFrame(randn(5, 5))
  1825. ax = df.plot.hist()
  1826. self._check_colors(ax.patches[::10], facecolors=default_colors[:5])
  1827. tm.close()
  1828. custom_colors = "rgcby"
  1829. ax = df.plot.hist(color=custom_colors)
  1830. self._check_colors(ax.patches[::10], facecolors=custom_colors)
  1831. tm.close()
  1832. from matplotlib import cm
  1833. # Test str -> colormap functionality
  1834. ax = df.plot.hist(colormap="jet")
  1835. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)]
  1836. self._check_colors(ax.patches[::10], facecolors=rgba_colors)
  1837. tm.close()
  1838. # Test colormap functionality
  1839. ax = df.plot.hist(colormap=cm.jet)
  1840. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)]
  1841. self._check_colors(ax.patches[::10], facecolors=rgba_colors)
  1842. tm.close()
  1843. ax = df.loc[:, [0]].plot.hist(color="DodgerBlue")
  1844. self._check_colors([ax.patches[0]], facecolors=["DodgerBlue"])
  1845. ax = df.plot(kind="hist", color="green")
  1846. self._check_colors(ax.patches[::10], facecolors=["green"] * 5)
  1847. tm.close()
  1848. @pytest.mark.slow
  1849. @td.skip_if_no_scipy
  1850. def test_kde_colors(self):
  1851. from matplotlib import cm
  1852. custom_colors = "rgcby"
  1853. df = DataFrame(rand(5, 5))
  1854. ax = df.plot.kde(color=custom_colors)
  1855. self._check_colors(ax.get_lines(), linecolors=custom_colors)
  1856. tm.close()
  1857. ax = df.plot.kde(colormap="jet")
  1858. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))]
  1859. self._check_colors(ax.get_lines(), linecolors=rgba_colors)
  1860. tm.close()
  1861. ax = df.plot.kde(colormap=cm.jet)
  1862. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))]
  1863. self._check_colors(ax.get_lines(), linecolors=rgba_colors)
  1864. @pytest.mark.slow
  1865. @td.skip_if_no_scipy
  1866. def test_kde_colors_and_styles_subplots(self):
  1867. from matplotlib import cm
  1868. default_colors = self._unpack_cycler(self.plt.rcParams)
  1869. df = DataFrame(randn(5, 5))
  1870. axes = df.plot(kind="kde", subplots=True)
  1871. for ax, c in zip(axes, list(default_colors)):
  1872. self._check_colors(ax.get_lines(), linecolors=[c])
  1873. tm.close()
  1874. # single color char
  1875. axes = df.plot(kind="kde", color="k", subplots=True)
  1876. for ax in axes:
  1877. self._check_colors(ax.get_lines(), linecolors=["k"])
  1878. tm.close()
  1879. # single color str
  1880. axes = df.plot(kind="kde", color="red", subplots=True)
  1881. for ax in axes:
  1882. self._check_colors(ax.get_lines(), linecolors=["red"])
  1883. tm.close()
  1884. custom_colors = "rgcby"
  1885. axes = df.plot(kind="kde", color=custom_colors, subplots=True)
  1886. for ax, c in zip(axes, list(custom_colors)):
  1887. self._check_colors(ax.get_lines(), linecolors=[c])
  1888. tm.close()
  1889. rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))]
  1890. for cmap in ["jet", cm.jet]:
  1891. axes = df.plot(kind="kde", colormap=cmap, subplots=True)
  1892. for ax, c in zip(axes, rgba_colors):
  1893. self._check_colors(ax.get_lines(), linecolors=[c])
  1894. tm.close()
  1895. # make color a list if plotting one column frame
  1896. # handles cases like df.plot(color='DodgerBlue')
  1897. axes = df.loc[:, [0]].plot(kind="kde", color="DodgerBlue", subplots=True)
  1898. self._check_colors(axes[0].lines, linecolors=["DodgerBlue"])
  1899. # single character style
  1900. axes = df.plot(kind="kde", style="r", subplots=True)
  1901. for ax in axes:
  1902. self._check_colors(ax.get_lines(), linecolors=["r"])
  1903. tm.close()
  1904. # list of styles
  1905. styles = list("rgcby")
  1906. axes = df.plot(kind="kde", style=styles, subplots=True)
  1907. for ax, c in zip(axes, styles):
  1908. self._check_colors(ax.get_lines(), linecolors=[c])
  1909. tm.close()
  1910. @pytest.mark.slow
  1911. def test_boxplot_colors(self):
  1912. def _check_colors(bp, box_c, whiskers_c, medians_c, caps_c="k", fliers_c=None):
  1913. # TODO: outside this func?
  1914. if fliers_c is None:
  1915. fliers_c = "k"
  1916. self._check_colors(bp["boxes"], linecolors=[box_c] * len(bp["boxes"]))
  1917. self._check_colors(
  1918. bp["whiskers"], linecolors=[whiskers_c] * len(bp["whiskers"])
  1919. )
  1920. self._check_colors(
  1921. bp["medians"], linecolors=[medians_c] * len(bp["medians"])
  1922. )
  1923. self._check_colors(bp["fliers"], linecolors=[fliers_c] * len(bp["fliers"]))
  1924. self._check_colors(bp["caps"], linecolors=[caps_c] * len(bp["caps"]))
  1925. default_colors = self._unpack_cycler(self.plt.rcParams)
  1926. df = DataFrame(randn(5, 5))
  1927. bp = df.plot.box(return_type="dict")
  1928. _check_colors(bp, default_colors[0], default_colors[0], default_colors[2])
  1929. tm.close()
  1930. dict_colors = dict(
  1931. boxes="#572923", whiskers="#982042", medians="#804823", caps="#123456"
  1932. )
  1933. bp = df.plot.box(color=dict_colors, sym="r+", return_type="dict")
  1934. _check_colors(
  1935. bp,
  1936. dict_colors["boxes"],
  1937. dict_colors["whiskers"],
  1938. dict_colors["medians"],
  1939. dict_colors["caps"],
  1940. "r",
  1941. )
  1942. tm.close()
  1943. # partial colors
  1944. dict_colors = dict(whiskers="c", medians="m")
  1945. bp = df.plot.box(color=dict_colors, return_type="dict")
  1946. _check_colors(bp, default_colors[0], "c", "m")
  1947. tm.close()
  1948. from matplotlib import cm
  1949. # Test str -> colormap functionality
  1950. bp = df.plot.box(colormap="jet", return_type="dict")
  1951. jet_colors = [cm.jet(n) for n in np.linspace(0, 1, 3)]
  1952. _check_colors(bp, jet_colors[0], jet_colors[0], jet_colors[2])
  1953. tm.close()
  1954. # Test colormap functionality
  1955. bp = df.plot.box(colormap=cm.jet, return_type="dict")
  1956. _check_colors(bp, jet_colors[0], jet_colors[0], jet_colors[2])
  1957. tm.close()
  1958. # string color is applied to all artists except fliers
  1959. bp = df.plot.box(color="DodgerBlue", return_type="dict")
  1960. _check_colors(bp, "DodgerBlue", "DodgerBlue", "DodgerBlue", "DodgerBlue")
  1961. # tuple is also applied to all artists except fliers
  1962. bp = df.plot.box(color=(0, 1, 0), sym="#123456", return_type="dict")
  1963. _check_colors(bp, (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), "#123456")
  1964. with pytest.raises(ValueError):
  1965. # Color contains invalid key results in ValueError
  1966. df.plot.box(color=dict(boxes="red", xxxx="blue"))
  1967. def test_default_color_cycle(self):
  1968. import matplotlib.pyplot as plt
  1969. import cycler
  1970. colors = list("rgbk")
  1971. plt.rcParams["axes.prop_cycle"] = cycler.cycler("color", colors)
  1972. df = DataFrame(randn(5, 3))
  1973. ax = df.plot()
  1974. expected = self._unpack_cycler(plt.rcParams)[:3]
  1975. self._check_colors(ax.get_lines(), linecolors=expected)
  1976. def test_unordered_ts(self):
  1977. df = DataFrame(
  1978. np.array([3.0, 2.0, 1.0]),
  1979. index=[date(2012, 10, 1), date(2012, 9, 1), date(2012, 8, 1)],
  1980. columns=["test"],
  1981. )
  1982. ax = df.plot()
  1983. xticks = ax.lines[0].get_xdata()
  1984. assert xticks[0] < xticks[1]
  1985. ydata = ax.lines[0].get_ydata()
  1986. tm.assert_numpy_array_equal(ydata, np.array([1.0, 2.0, 3.0]))
  1987. @td.skip_if_no_scipy
  1988. def test_kind_both_ways(self):
  1989. df = DataFrame({"x": [1, 2, 3]})
  1990. for kind in plotting.PlotAccessor._common_kinds:
  1991. df.plot(kind=kind)
  1992. getattr(df.plot, kind)()
  1993. for kind in ["scatter", "hexbin"]:
  1994. df.plot("x", "x", kind=kind)
  1995. getattr(df.plot, kind)("x", "x")
  1996. def test_all_invalid_plot_data(self):
  1997. df = DataFrame(list("abcd"))
  1998. for kind in plotting.PlotAccessor._common_kinds:
  1999. msg = "no numeric data to plot"
  2000. with pytest.raises(TypeError, match=msg):
  2001. df.plot(kind=kind)
  2002. @pytest.mark.slow
  2003. def test_partially_invalid_plot_data(self):
  2004. with tm.RNGContext(42):
  2005. df = DataFrame(randn(10, 2), dtype=object)
  2006. df[np.random.rand(df.shape[0]) > 0.5] = "a"
  2007. for kind in plotting.PlotAccessor._common_kinds:
  2008. msg = "no numeric data to plot"
  2009. with pytest.raises(TypeError, match=msg):
  2010. df.plot(kind=kind)
  2011. with tm.RNGContext(42):
  2012. # area plot doesn't support positive/negative mixed data
  2013. kinds = ["area"]
  2014. df = DataFrame(rand(10, 2), dtype=object)
  2015. df[np.random.rand(df.shape[0]) > 0.5] = "a"
  2016. for kind in kinds:
  2017. with pytest.raises(TypeError):
  2018. df.plot(kind=kind)
  2019. def test_invalid_kind(self):
  2020. df = DataFrame(randn(10, 2))
  2021. with pytest.raises(ValueError):
  2022. df.plot(kind="aasdf")
  2023. @pytest.mark.parametrize(
  2024. "x,y,lbl",
  2025. [
  2026. (["B", "C"], "A", "a"),
  2027. (["A"], ["B", "C"], ["b", "c"]),
  2028. ("A", ["B", "C"], "badlabel"),
  2029. ],
  2030. )
  2031. def test_invalid_xy_args(self, x, y, lbl):
  2032. # GH 18671, 19699 allows y to be list-like but not x
  2033. df = DataFrame({"A": [1, 2], "B": [3, 4], "C": [5, 6]})
  2034. with pytest.raises(ValueError):
  2035. df.plot(x=x, y=y, label=lbl)
  2036. @pytest.mark.parametrize("x,y", [("A", "B"), (["A"], "B")])
  2037. def test_invalid_xy_args_dup_cols(self, x, y):
  2038. # GH 18671, 19699 allows y to be list-like but not x
  2039. df = DataFrame([[1, 3, 5], [2, 4, 6]], columns=list("AAB"))
  2040. with pytest.raises(ValueError):
  2041. df.plot(x=x, y=y)
  2042. @pytest.mark.parametrize(
  2043. "x,y,lbl,colors",
  2044. [
  2045. ("A", ["B"], ["b"], ["red"]),
  2046. ("A", ["B", "C"], ["b", "c"], ["red", "blue"]),
  2047. (0, [1, 2], ["bokeh", "cython"], ["green", "yellow"]),
  2048. ],
  2049. )
  2050. def test_y_listlike(self, x, y, lbl, colors):
  2051. # GH 19699: tests list-like y and verifies lbls & colors
  2052. df = DataFrame({"A": [1, 2], "B": [3, 4], "C": [5, 6]})
  2053. _check_plot_works(df.plot, x="A", y=y, label=lbl)
  2054. ax = df.plot(x=x, y=y, label=lbl, color=colors)
  2055. assert len(ax.lines) == len(y)
  2056. self._check_colors(ax.get_lines(), linecolors=colors)
  2057. @pytest.mark.parametrize("x,y,colnames", [(0, 1, ["A", "B"]), (1, 0, [0, 1])])
  2058. def test_xy_args_integer(self, x, y, colnames):
  2059. # GH 20056: tests integer args for xy and checks col names
  2060. df = DataFrame({"A": [1, 2], "B": [3, 4]})
  2061. df.columns = colnames
  2062. _check_plot_works(df.plot, x=x, y=y)
  2063. @pytest.mark.slow
  2064. def test_hexbin_basic(self):
  2065. df = self.hexbin_df
  2066. ax = df.plot.hexbin(x="A", y="B", gridsize=10)
  2067. # TODO: need better way to test. This just does existence.
  2068. assert len(ax.collections) == 1
  2069. # GH 6951
  2070. axes = df.plot.hexbin(x="A", y="B", subplots=True)
  2071. # hexbin should have 2 axes in the figure, 1 for plotting and another
  2072. # is colorbar
  2073. assert len(axes[0].figure.axes) == 2
  2074. # return value is single axes
  2075. self._check_axes_shape(axes, axes_num=1, layout=(1, 1))
  2076. @pytest.mark.slow
  2077. def test_hexbin_with_c(self):
  2078. df = self.hexbin_df
  2079. ax = df.plot.hexbin(x="A", y="B", C="C")
  2080. assert len(ax.collections) == 1
  2081. ax = df.plot.hexbin(x="A", y="B", C="C", reduce_C_function=np.std)
  2082. assert len(ax.collections) == 1
  2083. @pytest.mark.slow
  2084. def test_hexbin_cmap(self):
  2085. df = self.hexbin_df
  2086. # Default to BuGn
  2087. ax = df.plot.hexbin(x="A", y="B")
  2088. assert ax.collections[0].cmap.name == "BuGn"
  2089. cm = "cubehelix"
  2090. ax = df.plot.hexbin(x="A", y="B", colormap=cm)
  2091. assert ax.collections[0].cmap.name == cm
  2092. @pytest.mark.slow
  2093. def test_no_color_bar(self):
  2094. df = self.hexbin_df
  2095. ax = df.plot.hexbin(x="A", y="B", colorbar=None)
  2096. assert ax.collections[0].colorbar is None
  2097. @pytest.mark.slow
  2098. def test_allow_cmap(self):
  2099. df = self.hexbin_df
  2100. ax = df.plot.hexbin(x="A", y="B", cmap="YlGn")
  2101. assert ax.collections[0].cmap.name == "YlGn"
  2102. with pytest.raises(TypeError):
  2103. df.plot.hexbin(x="A", y="B", cmap="YlGn", colormap="BuGn")
  2104. @pytest.mark.slow
  2105. def test_pie_df(self):
  2106. df = DataFrame(
  2107. np.random.rand(5, 3),
  2108. columns=["X", "Y", "Z"],
  2109. index=["a", "b", "c", "d", "e"],
  2110. )
  2111. with pytest.raises(ValueError):
  2112. df.plot.pie()
  2113. ax = _check_plot_works(df.plot.pie, y="Y")
  2114. self._check_text_labels(ax.texts, df.index)
  2115. ax = _check_plot_works(df.plot.pie, y=2)
  2116. self._check_text_labels(ax.texts, df.index)
  2117. # _check_plot_works adds an ax so catch warning. see GH #13188
  2118. with tm.assert_produces_warning(UserWarning):
  2119. axes = _check_plot_works(df.plot.pie, subplots=True)
  2120. assert len(axes) == len(df.columns)
  2121. for ax in axes:
  2122. self._check_text_labels(ax.texts, df.index)
  2123. for ax, ylabel in zip(axes, df.columns):
  2124. assert ax.get_ylabel() == ylabel
  2125. labels = ["A", "B", "C", "D", "E"]
  2126. color_args = ["r", "g", "b", "c", "m"]
  2127. with tm.assert_produces_warning(UserWarning):
  2128. axes = _check_plot_works(
  2129. df.plot.pie, subplots=True, labels=labels, colors=color_args
  2130. )
  2131. assert len(axes) == len(df.columns)
  2132. for ax in axes:
  2133. self._check_text_labels(ax.texts, labels)
  2134. self._check_colors(ax.patches, facecolors=color_args)
  2135. def test_pie_df_nan(self):
  2136. df = DataFrame(np.random.rand(4, 4))
  2137. for i in range(4):
  2138. df.iloc[i, i] = np.nan
  2139. fig, axes = self.plt.subplots(ncols=4)
  2140. df.plot.pie(subplots=True, ax=axes, legend=True)
  2141. base_expected = ["0", "1", "2", "3"]
  2142. for i, ax in enumerate(axes):
  2143. expected = list(base_expected) # force copy
  2144. expected[i] = ""
  2145. result = [x.get_text() for x in ax.texts]
  2146. assert result == expected
  2147. # legend labels
  2148. # NaN's not included in legend with subplots
  2149. # see https://github.com/pandas-dev/pandas/issues/8390
  2150. assert [x.get_text() for x in ax.get_legend().get_texts()] == base_expected[
  2151. :i
  2152. ] + base_expected[i + 1 :]
  2153. @pytest.mark.slow
  2154. def test_errorbar_plot(self):
  2155. with warnings.catch_warnings():
  2156. d = {"x": np.arange(12), "y": np.arange(12, 0, -1)}
  2157. df = DataFrame(d)
  2158. d_err = {"x": np.ones(12) * 0.2, "y": np.ones(12) * 0.4}
  2159. df_err = DataFrame(d_err)
  2160. # check line plots
  2161. ax = _check_plot_works(df.plot, yerr=df_err, logy=True)
  2162. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2163. ax = _check_plot_works(df.plot, yerr=df_err, logx=True, logy=True)
  2164. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2165. ax = _check_plot_works(df.plot, yerr=df_err, loglog=True)
  2166. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2167. kinds = ["line", "bar", "barh"]
  2168. for kind in kinds:
  2169. ax = _check_plot_works(df.plot, yerr=df_err["x"], kind=kind)
  2170. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2171. ax = _check_plot_works(df.plot, yerr=d_err, kind=kind)
  2172. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2173. ax = _check_plot_works(df.plot, yerr=df_err, xerr=df_err, kind=kind)
  2174. self._check_has_errorbars(ax, xerr=2, yerr=2)
  2175. ax = _check_plot_works(
  2176. df.plot, yerr=df_err["x"], xerr=df_err["x"], kind=kind
  2177. )
  2178. self._check_has_errorbars(ax, xerr=2, yerr=2)
  2179. ax = _check_plot_works(df.plot, xerr=0.2, yerr=0.2, kind=kind)
  2180. self._check_has_errorbars(ax, xerr=2, yerr=2)
  2181. # _check_plot_works adds an ax so catch warning. see GH #13188
  2182. axes = _check_plot_works(
  2183. df.plot, yerr=df_err, xerr=df_err, subplots=True, kind=kind
  2184. )
  2185. self._check_has_errorbars(axes, xerr=1, yerr=1)
  2186. ax = _check_plot_works(
  2187. (df + 1).plot, yerr=df_err, xerr=df_err, kind="bar", log=True
  2188. )
  2189. self._check_has_errorbars(ax, xerr=2, yerr=2)
  2190. # yerr is raw error values
  2191. ax = _check_plot_works(df["y"].plot, yerr=np.ones(12) * 0.4)
  2192. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2193. ax = _check_plot_works(df.plot, yerr=np.ones((2, 12)) * 0.4)
  2194. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2195. # yerr is column name
  2196. for yerr in ["yerr", "誤差"]:
  2197. s_df = df.copy()
  2198. s_df[yerr] = np.ones(12) * 0.2
  2199. ax = _check_plot_works(s_df.plot, yerr=yerr)
  2200. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2201. ax = _check_plot_works(s_df.plot, y="y", x="x", yerr=yerr)
  2202. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2203. with pytest.raises(ValueError):
  2204. df.plot(yerr=np.random.randn(11))
  2205. df_err = DataFrame({"x": ["zzz"] * 12, "y": ["zzz"] * 12})
  2206. with pytest.raises((ValueError, TypeError)):
  2207. df.plot(yerr=df_err)
  2208. @pytest.mark.xfail(reason="Iterator is consumed", raises=ValueError)
  2209. @pytest.mark.slow
  2210. def test_errorbar_plot_iterator(self):
  2211. with warnings.catch_warnings():
  2212. d = {"x": np.arange(12), "y": np.arange(12, 0, -1)}
  2213. df = DataFrame(d)
  2214. # yerr is iterator
  2215. ax = _check_plot_works(df.plot, yerr=itertools.repeat(0.1, len(df)))
  2216. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2217. @pytest.mark.slow
  2218. def test_errorbar_with_integer_column_names(self):
  2219. # test with integer column names
  2220. df = DataFrame(np.random.randn(10, 2))
  2221. df_err = DataFrame(np.random.randn(10, 2))
  2222. ax = _check_plot_works(df.plot, yerr=df_err)
  2223. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2224. ax = _check_plot_works(df.plot, y=0, yerr=1)
  2225. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2226. @pytest.mark.slow
  2227. def test_errorbar_with_partial_columns(self):
  2228. df = DataFrame(np.random.randn(10, 3))
  2229. df_err = DataFrame(np.random.randn(10, 2), columns=[0, 2])
  2230. kinds = ["line", "bar"]
  2231. for kind in kinds:
  2232. ax = _check_plot_works(df.plot, yerr=df_err, kind=kind)
  2233. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2234. ix = date_range("1/1/2000", periods=10, freq="M")
  2235. df.set_index(ix, inplace=True)
  2236. df_err.set_index(ix, inplace=True)
  2237. ax = _check_plot_works(df.plot, yerr=df_err, kind="line")
  2238. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2239. d = {"x": np.arange(12), "y": np.arange(12, 0, -1)}
  2240. df = DataFrame(d)
  2241. d_err = {"x": np.ones(12) * 0.2, "z": np.ones(12) * 0.4}
  2242. df_err = DataFrame(d_err)
  2243. for err in [d_err, df_err]:
  2244. ax = _check_plot_works(df.plot, yerr=err)
  2245. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2246. @pytest.mark.slow
  2247. def test_errorbar_timeseries(self):
  2248. with warnings.catch_warnings():
  2249. d = {"x": np.arange(12), "y": np.arange(12, 0, -1)}
  2250. d_err = {"x": np.ones(12) * 0.2, "y": np.ones(12) * 0.4}
  2251. # check time-series plots
  2252. ix = date_range("1/1/2000", "1/1/2001", freq="M")
  2253. tdf = DataFrame(d, index=ix)
  2254. tdf_err = DataFrame(d_err, index=ix)
  2255. kinds = ["line", "bar", "barh"]
  2256. for kind in kinds:
  2257. ax = _check_plot_works(tdf.plot, yerr=tdf_err, kind=kind)
  2258. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2259. ax = _check_plot_works(tdf.plot, yerr=d_err, kind=kind)
  2260. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2261. ax = _check_plot_works(tdf.plot, y="y", yerr=tdf_err["x"], kind=kind)
  2262. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2263. ax = _check_plot_works(tdf.plot, y="y", yerr="x", kind=kind)
  2264. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2265. ax = _check_plot_works(tdf.plot, yerr=tdf_err, kind=kind)
  2266. self._check_has_errorbars(ax, xerr=0, yerr=2)
  2267. # _check_plot_works adds an ax so catch warning. see GH #13188
  2268. axes = _check_plot_works(
  2269. tdf.plot, kind=kind, yerr=tdf_err, subplots=True
  2270. )
  2271. self._check_has_errorbars(axes, xerr=0, yerr=1)
  2272. def test_errorbar_asymmetrical(self):
  2273. np.random.seed(0)
  2274. err = np.random.rand(3, 2, 5)
  2275. # each column is [0, 1, 2, 3, 4], [3, 4, 5, 6, 7]...
  2276. df = DataFrame(np.arange(15).reshape(3, 5)).T
  2277. ax = df.plot(yerr=err, xerr=err / 2)
  2278. yerr_0_0 = ax.collections[1].get_paths()[0].vertices[:, 1]
  2279. expected_0_0 = err[0, :, 0] * np.array([-1, 1])
  2280. tm.assert_almost_equal(yerr_0_0, expected_0_0)
  2281. with pytest.raises(ValueError):
  2282. df.plot(yerr=err.T)
  2283. tm.close()
  2284. def test_table(self):
  2285. df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10]))
  2286. _check_plot_works(df.plot, table=True)
  2287. _check_plot_works(df.plot, table=df)
  2288. ax = df.plot()
  2289. assert len(ax.tables) == 0
  2290. plotting.table(ax, df.T)
  2291. assert len(ax.tables) == 1
  2292. def test_errorbar_scatter(self):
  2293. df = DataFrame(np.random.randn(5, 2), index=range(5), columns=["x", "y"])
  2294. df_err = DataFrame(
  2295. np.random.randn(5, 2) / 5, index=range(5), columns=["x", "y"]
  2296. )
  2297. ax = _check_plot_works(df.plot.scatter, x="x", y="y")
  2298. self._check_has_errorbars(ax, xerr=0, yerr=0)
  2299. ax = _check_plot_works(df.plot.scatter, x="x", y="y", xerr=df_err)
  2300. self._check_has_errorbars(ax, xerr=1, yerr=0)
  2301. ax = _check_plot_works(df.plot.scatter, x="x", y="y", yerr=df_err)
  2302. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2303. ax = _check_plot_works(df.plot.scatter, x="x", y="y", xerr=df_err, yerr=df_err)
  2304. self._check_has_errorbars(ax, xerr=1, yerr=1)
  2305. def _check_errorbar_color(containers, expected, has_err="has_xerr"):
  2306. lines = []
  2307. errs = [c.lines for c in ax.containers if getattr(c, has_err, False)][0]
  2308. for el in errs:
  2309. if is_list_like(el):
  2310. lines.extend(el)
  2311. else:
  2312. lines.append(el)
  2313. err_lines = [x for x in lines if x in ax.collections]
  2314. self._check_colors(
  2315. err_lines, linecolors=np.array([expected] * len(err_lines))
  2316. )
  2317. # GH 8081
  2318. df = DataFrame(np.random.randn(10, 5), columns=["a", "b", "c", "d", "e"])
  2319. ax = df.plot.scatter(x="a", y="b", xerr="d", yerr="e", c="red")
  2320. self._check_has_errorbars(ax, xerr=1, yerr=1)
  2321. _check_errorbar_color(ax.containers, "red", has_err="has_xerr")
  2322. _check_errorbar_color(ax.containers, "red", has_err="has_yerr")
  2323. ax = df.plot.scatter(x="a", y="b", yerr="e", color="green")
  2324. self._check_has_errorbars(ax, xerr=0, yerr=1)
  2325. _check_errorbar_color(ax.containers, "green", has_err="has_yerr")
  2326. @pytest.mark.slow
  2327. def test_sharex_and_ax(self):
  2328. # https://github.com/pandas-dev/pandas/issues/9737 using gridspec,
  2329. # the axis in fig.get_axis() are sorted differently than pandas
  2330. # expected them, so make sure that only the right ones are removed
  2331. import matplotlib.pyplot as plt
  2332. plt.close("all")
  2333. gs, axes = _generate_4_axes_via_gridspec()
  2334. df = DataFrame(
  2335. {
  2336. "a": [1, 2, 3, 4, 5, 6],
  2337. "b": [1, 2, 3, 4, 5, 6],
  2338. "c": [1, 2, 3, 4, 5, 6],
  2339. "d": [1, 2, 3, 4, 5, 6],
  2340. }
  2341. )
  2342. def _check(axes):
  2343. for ax in axes:
  2344. assert len(ax.lines) == 1
  2345. self._check_visible(ax.get_yticklabels(), visible=True)
  2346. for ax in [axes[0], axes[2]]:
  2347. self._check_visible(ax.get_xticklabels(), visible=False)
  2348. self._check_visible(ax.get_xticklabels(minor=True), visible=False)
  2349. for ax in [axes[1], axes[3]]:
  2350. self._check_visible(ax.get_xticklabels(), visible=True)
  2351. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2352. for ax in axes:
  2353. df.plot(x="a", y="b", title="title", ax=ax, sharex=True)
  2354. gs.tight_layout(plt.gcf())
  2355. _check(axes)
  2356. tm.close()
  2357. gs, axes = _generate_4_axes_via_gridspec()
  2358. with tm.assert_produces_warning(UserWarning):
  2359. axes = df.plot(subplots=True, ax=axes, sharex=True)
  2360. _check(axes)
  2361. tm.close()
  2362. gs, axes = _generate_4_axes_via_gridspec()
  2363. # without sharex, no labels should be touched!
  2364. for ax in axes:
  2365. df.plot(x="a", y="b", title="title", ax=ax)
  2366. gs.tight_layout(plt.gcf())
  2367. for ax in axes:
  2368. assert len(ax.lines) == 1
  2369. self._check_visible(ax.get_yticklabels(), visible=True)
  2370. self._check_visible(ax.get_xticklabels(), visible=True)
  2371. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2372. tm.close()
  2373. @pytest.mark.slow
  2374. def test_sharey_and_ax(self):
  2375. # https://github.com/pandas-dev/pandas/issues/9737 using gridspec,
  2376. # the axis in fig.get_axis() are sorted differently than pandas
  2377. # expected them, so make sure that only the right ones are removed
  2378. import matplotlib.pyplot as plt
  2379. gs, axes = _generate_4_axes_via_gridspec()
  2380. df = DataFrame(
  2381. {
  2382. "a": [1, 2, 3, 4, 5, 6],
  2383. "b": [1, 2, 3, 4, 5, 6],
  2384. "c": [1, 2, 3, 4, 5, 6],
  2385. "d": [1, 2, 3, 4, 5, 6],
  2386. }
  2387. )
  2388. def _check(axes):
  2389. for ax in axes:
  2390. assert len(ax.lines) == 1
  2391. self._check_visible(ax.get_xticklabels(), visible=True)
  2392. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2393. for ax in [axes[0], axes[1]]:
  2394. self._check_visible(ax.get_yticklabels(), visible=True)
  2395. for ax in [axes[2], axes[3]]:
  2396. self._check_visible(ax.get_yticklabels(), visible=False)
  2397. for ax in axes:
  2398. df.plot(x="a", y="b", title="title", ax=ax, sharey=True)
  2399. gs.tight_layout(plt.gcf())
  2400. _check(axes)
  2401. tm.close()
  2402. gs, axes = _generate_4_axes_via_gridspec()
  2403. with tm.assert_produces_warning(UserWarning):
  2404. axes = df.plot(subplots=True, ax=axes, sharey=True)
  2405. gs.tight_layout(plt.gcf())
  2406. _check(axes)
  2407. tm.close()
  2408. gs, axes = _generate_4_axes_via_gridspec()
  2409. # without sharex, no labels should be touched!
  2410. for ax in axes:
  2411. df.plot(x="a", y="b", title="title", ax=ax)
  2412. gs.tight_layout(plt.gcf())
  2413. for ax in axes:
  2414. assert len(ax.lines) == 1
  2415. self._check_visible(ax.get_yticklabels(), visible=True)
  2416. self._check_visible(ax.get_xticklabels(), visible=True)
  2417. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2418. @td.skip_if_no_scipy
  2419. def test_memory_leak(self):
  2420. """ Check that every plot type gets properly collected. """
  2421. import weakref
  2422. import gc
  2423. results = {}
  2424. for kind in plotting.PlotAccessor._all_kinds:
  2425. args = {}
  2426. if kind in ["hexbin", "scatter", "pie"]:
  2427. df = self.hexbin_df
  2428. args = {"x": "A", "y": "B"}
  2429. elif kind == "area":
  2430. df = self.tdf.abs()
  2431. else:
  2432. df = self.tdf
  2433. # Use a weakref so we can see if the object gets collected without
  2434. # also preventing it from being collected
  2435. results[kind] = weakref.proxy(df.plot(kind=kind, **args))
  2436. # have matplotlib delete all the figures
  2437. tm.close()
  2438. # force a garbage collection
  2439. gc.collect()
  2440. for key in results:
  2441. # check that every plot was collected
  2442. with pytest.raises(ReferenceError):
  2443. # need to actually access something to get an error
  2444. results[key].lines
  2445. @pytest.mark.slow
  2446. def test_df_subplots_patterns_minorticks(self):
  2447. # GH 10657
  2448. import matplotlib.pyplot as plt
  2449. df = DataFrame(
  2450. np.random.randn(10, 2),
  2451. index=date_range("1/1/2000", periods=10),
  2452. columns=list("AB"),
  2453. )
  2454. # shared subplots
  2455. fig, axes = plt.subplots(2, 1, sharex=True)
  2456. axes = df.plot(subplots=True, ax=axes)
  2457. for ax in axes:
  2458. assert len(ax.lines) == 1
  2459. self._check_visible(ax.get_yticklabels(), visible=True)
  2460. # xaxis of 1st ax must be hidden
  2461. self._check_visible(axes[0].get_xticklabels(), visible=False)
  2462. self._check_visible(axes[0].get_xticklabels(minor=True), visible=False)
  2463. self._check_visible(axes[1].get_xticklabels(), visible=True)
  2464. self._check_visible(axes[1].get_xticklabels(minor=True), visible=True)
  2465. tm.close()
  2466. fig, axes = plt.subplots(2, 1)
  2467. with tm.assert_produces_warning(UserWarning):
  2468. axes = df.plot(subplots=True, ax=axes, sharex=True)
  2469. for ax in axes:
  2470. assert len(ax.lines) == 1
  2471. self._check_visible(ax.get_yticklabels(), visible=True)
  2472. # xaxis of 1st ax must be hidden
  2473. self._check_visible(axes[0].get_xticklabels(), visible=False)
  2474. self._check_visible(axes[0].get_xticklabels(minor=True), visible=False)
  2475. self._check_visible(axes[1].get_xticklabels(), visible=True)
  2476. self._check_visible(axes[1].get_xticklabels(minor=True), visible=True)
  2477. tm.close()
  2478. # not shared
  2479. fig, axes = plt.subplots(2, 1)
  2480. axes = df.plot(subplots=True, ax=axes)
  2481. for ax in axes:
  2482. assert len(ax.lines) == 1
  2483. self._check_visible(ax.get_yticklabels(), visible=True)
  2484. self._check_visible(ax.get_xticklabels(), visible=True)
  2485. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2486. tm.close()
  2487. @pytest.mark.slow
  2488. def test_df_gridspec_patterns(self):
  2489. # GH 10819
  2490. import matplotlib.pyplot as plt
  2491. import matplotlib.gridspec as gridspec
  2492. ts = Series(np.random.randn(10), index=date_range("1/1/2000", periods=10))
  2493. df = DataFrame(np.random.randn(10, 2), index=ts.index, columns=list("AB"))
  2494. def _get_vertical_grid():
  2495. gs = gridspec.GridSpec(3, 1)
  2496. fig = plt.figure()
  2497. ax1 = fig.add_subplot(gs[:2, :])
  2498. ax2 = fig.add_subplot(gs[2, :])
  2499. return ax1, ax2
  2500. def _get_horizontal_grid():
  2501. gs = gridspec.GridSpec(1, 3)
  2502. fig = plt.figure()
  2503. ax1 = fig.add_subplot(gs[:, :2])
  2504. ax2 = fig.add_subplot(gs[:, 2])
  2505. return ax1, ax2
  2506. for ax1, ax2 in [_get_vertical_grid(), _get_horizontal_grid()]:
  2507. ax1 = ts.plot(ax=ax1)
  2508. assert len(ax1.lines) == 1
  2509. ax2 = df.plot(ax=ax2)
  2510. assert len(ax2.lines) == 2
  2511. for ax in [ax1, ax2]:
  2512. self._check_visible(ax.get_yticklabels(), visible=True)
  2513. self._check_visible(ax.get_xticklabels(), visible=True)
  2514. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2515. tm.close()
  2516. # subplots=True
  2517. for ax1, ax2 in [_get_vertical_grid(), _get_horizontal_grid()]:
  2518. axes = df.plot(subplots=True, ax=[ax1, ax2])
  2519. assert len(ax1.lines) == 1
  2520. assert len(ax2.lines) == 1
  2521. for ax in axes:
  2522. self._check_visible(ax.get_yticklabels(), visible=True)
  2523. self._check_visible(ax.get_xticklabels(), visible=True)
  2524. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2525. tm.close()
  2526. # vertical / subplots / sharex=True / sharey=True
  2527. ax1, ax2 = _get_vertical_grid()
  2528. with tm.assert_produces_warning(UserWarning):
  2529. axes = df.plot(subplots=True, ax=[ax1, ax2], sharex=True, sharey=True)
  2530. assert len(axes[0].lines) == 1
  2531. assert len(axes[1].lines) == 1
  2532. for ax in [ax1, ax2]:
  2533. # yaxis are visible because there is only one column
  2534. self._check_visible(ax.get_yticklabels(), visible=True)
  2535. # xaxis of axes0 (top) are hidden
  2536. self._check_visible(axes[0].get_xticklabels(), visible=False)
  2537. self._check_visible(axes[0].get_xticklabels(minor=True), visible=False)
  2538. self._check_visible(axes[1].get_xticklabels(), visible=True)
  2539. self._check_visible(axes[1].get_xticklabels(minor=True), visible=True)
  2540. tm.close()
  2541. # horizontal / subplots / sharex=True / sharey=True
  2542. ax1, ax2 = _get_horizontal_grid()
  2543. with tm.assert_produces_warning(UserWarning):
  2544. axes = df.plot(subplots=True, ax=[ax1, ax2], sharex=True, sharey=True)
  2545. assert len(axes[0].lines) == 1
  2546. assert len(axes[1].lines) == 1
  2547. self._check_visible(axes[0].get_yticklabels(), visible=True)
  2548. # yaxis of axes1 (right) are hidden
  2549. self._check_visible(axes[1].get_yticklabels(), visible=False)
  2550. for ax in [ax1, ax2]:
  2551. # xaxis are visible because there is only one column
  2552. self._check_visible(ax.get_xticklabels(), visible=True)
  2553. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2554. tm.close()
  2555. # boxed
  2556. def _get_boxed_grid():
  2557. gs = gridspec.GridSpec(3, 3)
  2558. fig = plt.figure()
  2559. ax1 = fig.add_subplot(gs[:2, :2])
  2560. ax2 = fig.add_subplot(gs[:2, 2])
  2561. ax3 = fig.add_subplot(gs[2, :2])
  2562. ax4 = fig.add_subplot(gs[2, 2])
  2563. return ax1, ax2, ax3, ax4
  2564. axes = _get_boxed_grid()
  2565. df = DataFrame(np.random.randn(10, 4), index=ts.index, columns=list("ABCD"))
  2566. axes = df.plot(subplots=True, ax=axes)
  2567. for ax in axes:
  2568. assert len(ax.lines) == 1
  2569. # axis are visible because these are not shared
  2570. self._check_visible(ax.get_yticklabels(), visible=True)
  2571. self._check_visible(ax.get_xticklabels(), visible=True)
  2572. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2573. tm.close()
  2574. # subplots / sharex=True / sharey=True
  2575. axes = _get_boxed_grid()
  2576. with tm.assert_produces_warning(UserWarning):
  2577. axes = df.plot(subplots=True, ax=axes, sharex=True, sharey=True)
  2578. for ax in axes:
  2579. assert len(ax.lines) == 1
  2580. for ax in [axes[0], axes[2]]: # left column
  2581. self._check_visible(ax.get_yticklabels(), visible=True)
  2582. for ax in [axes[1], axes[3]]: # right column
  2583. self._check_visible(ax.get_yticklabels(), visible=False)
  2584. for ax in [axes[0], axes[1]]: # top row
  2585. self._check_visible(ax.get_xticklabels(), visible=False)
  2586. self._check_visible(ax.get_xticklabels(minor=True), visible=False)
  2587. for ax in [axes[2], axes[3]]: # bottom row
  2588. self._check_visible(ax.get_xticklabels(), visible=True)
  2589. self._check_visible(ax.get_xticklabels(minor=True), visible=True)
  2590. tm.close()
  2591. @pytest.mark.slow
  2592. def test_df_grid_settings(self):
  2593. # Make sure plot defaults to rcParams['axes.grid'] setting, GH 9792
  2594. self._check_grid_settings(
  2595. DataFrame({"a": [1, 2, 3], "b": [2, 3, 4]}),
  2596. plotting.PlotAccessor._dataframe_kinds,
  2597. kws={"x": "a", "y": "b"},
  2598. )
  2599. def test_invalid_colormap(self):
  2600. df = DataFrame(randn(3, 2), columns=["A", "B"])
  2601. with pytest.raises(ValueError):
  2602. df.plot(colormap="invalid_colormap")
  2603. def test_plain_axes(self):
  2604. # supplied ax itself is a SubplotAxes, but figure contains also
  2605. # a plain Axes object (GH11556)
  2606. fig, ax = self.plt.subplots()
  2607. fig.add_axes([0.2, 0.2, 0.2, 0.2])
  2608. Series(rand(10)).plot(ax=ax)
  2609. # supplied ax itself is a plain Axes, but because the cmap keyword
  2610. # a new ax is created for the colorbar -> also multiples axes (GH11520)
  2611. df = DataFrame({"a": randn(8), "b": randn(8)})
  2612. fig = self.plt.figure()
  2613. ax = fig.add_axes((0, 0, 1, 1))
  2614. df.plot(kind="scatter", ax=ax, x="a", y="b", c="a", cmap="hsv")
  2615. # other examples
  2616. fig, ax = self.plt.subplots()
  2617. from mpl_toolkits.axes_grid1 import make_axes_locatable
  2618. divider = make_axes_locatable(ax)
  2619. cax = divider.append_axes("right", size="5%", pad=0.05)
  2620. Series(rand(10)).plot(ax=ax)
  2621. Series(rand(10)).plot(ax=cax)
  2622. fig, ax = self.plt.subplots()
  2623. from mpl_toolkits.axes_grid1.inset_locator import inset_axes
  2624. iax = inset_axes(ax, width="30%", height=1.0, loc=3)
  2625. Series(rand(10)).plot(ax=ax)
  2626. Series(rand(10)).plot(ax=iax)
  2627. def test_passed_bar_colors(self):
  2628. import matplotlib as mpl
  2629. color_tuples = [(0.9, 0, 0, 1), (0, 0.9, 0, 1), (0, 0, 0.9, 1)]
  2630. colormap = mpl.colors.ListedColormap(color_tuples)
  2631. barplot = pd.DataFrame([[1, 2, 3]]).plot(kind="bar", cmap=colormap)
  2632. assert color_tuples == [c.get_facecolor() for c in barplot.patches]
  2633. def test_rcParams_bar_colors(self):
  2634. import matplotlib as mpl
  2635. color_tuples = [(0.9, 0, 0, 1), (0, 0.9, 0, 1), (0, 0, 0.9, 1)]
  2636. with mpl.rc_context(rc={"axes.prop_cycle": mpl.cycler("color", color_tuples)}):
  2637. barplot = pd.DataFrame([[1, 2, 3]]).plot(kind="bar")
  2638. assert color_tuples == [c.get_facecolor() for c in barplot.patches]
  2639. @pytest.mark.parametrize("method", ["line", "barh", "bar"])
  2640. def test_secondary_axis_font_size(self, method):
  2641. # GH: 12565
  2642. df = (
  2643. pd.DataFrame(np.random.randn(15, 2), columns=list("AB"))
  2644. .assign(C=lambda df: df.B.cumsum())
  2645. .assign(D=lambda df: df.C * 1.1)
  2646. )
  2647. fontsize = 20
  2648. sy = ["C", "D"]
  2649. kwargs = dict(secondary_y=sy, fontsize=fontsize, mark_right=True)
  2650. ax = getattr(df.plot, method)(**kwargs)
  2651. self._check_ticks_props(axes=ax.right_ax, ylabelsize=fontsize)
  2652. @pytest.mark.slow
  2653. def test_x_string_values_ticks(self):
  2654. # Test if string plot index have a fixed xtick position
  2655. # GH: 7612, GH: 22334
  2656. df = pd.DataFrame(
  2657. {
  2658. "sales": [3, 2, 3],
  2659. "visits": [20, 42, 28],
  2660. "day": ["Monday", "Tuesday", "Wednesday"],
  2661. }
  2662. )
  2663. ax = df.plot.area(x="day")
  2664. ax.set_xlim(-1, 3)
  2665. xticklabels = [t.get_text() for t in ax.get_xticklabels()]
  2666. labels_position = dict(zip(xticklabels, ax.get_xticks()))
  2667. # Testing if the label stayed at the right position
  2668. assert labels_position["Monday"] == 0.0
  2669. assert labels_position["Tuesday"] == 1.0
  2670. assert labels_position["Wednesday"] == 2.0
  2671. @pytest.mark.slow
  2672. def test_x_multiindex_values_ticks(self):
  2673. # Test if multiindex plot index have a fixed xtick position
  2674. # GH: 15912
  2675. index = pd.MultiIndex.from_product([[2012, 2013], [1, 2]])
  2676. df = pd.DataFrame(np.random.randn(4, 2), columns=["A", "B"], index=index)
  2677. ax = df.plot()
  2678. ax.set_xlim(-1, 4)
  2679. xticklabels = [t.get_text() for t in ax.get_xticklabels()]
  2680. labels_position = dict(zip(xticklabels, ax.get_xticks()))
  2681. # Testing if the label stayed at the right position
  2682. assert labels_position["(2012, 1)"] == 0.0
  2683. assert labels_position["(2012, 2)"] == 1.0
  2684. assert labels_position["(2013, 1)"] == 2.0
  2685. assert labels_position["(2013, 2)"] == 3.0
  2686. @pytest.mark.parametrize("kind", ["line", "area"])
  2687. def test_xlim_plot_line(self, kind):
  2688. # test if xlim is set correctly in plot.line and plot.area
  2689. # GH 27686
  2690. df = pd.DataFrame([2, 4], index=[1, 2])
  2691. ax = df.plot(kind=kind)
  2692. xlims = ax.get_xlim()
  2693. assert xlims[0] < 1
  2694. assert xlims[1] > 2
  2695. def test_xlim_plot_line_correctly_in_mixed_plot_type(self):
  2696. # test if xlim is set correctly when ax contains multiple different kinds
  2697. # of plots, GH 27686
  2698. fig, ax = self.plt.subplots()
  2699. indexes = ["k1", "k2", "k3", "k4"]
  2700. df = pd.DataFrame(
  2701. {
  2702. "s1": [1000, 2000, 1500, 2000],
  2703. "s2": [900, 1400, 2000, 3000],
  2704. "s3": [1500, 1500, 1600, 1200],
  2705. "secondary_y": [1, 3, 4, 3],
  2706. },
  2707. index=indexes,
  2708. )
  2709. df[["s1", "s2", "s3"]].plot.bar(ax=ax, stacked=False)
  2710. df[["secondary_y"]].plot(ax=ax, secondary_y=True)
  2711. xlims = ax.get_xlim()
  2712. assert xlims[0] < 0
  2713. assert xlims[1] > 3
  2714. # make sure axis labels are plotted correctly as well
  2715. xticklabels = [t.get_text() for t in ax.get_xticklabels()]
  2716. assert xticklabels == indexes
  2717. def test_subplots_sharex_false(self):
  2718. # test when sharex is set to False, two plots should have different
  2719. # labels, GH 25160
  2720. df = pd.DataFrame(np.random.rand(10, 2))
  2721. df.iloc[5:, 1] = np.nan
  2722. df.iloc[:5, 0] = np.nan
  2723. figs, axs = self.plt.subplots(2, 1)
  2724. df.plot.line(ax=axs, subplots=True, sharex=False)
  2725. expected_ax1 = np.arange(4.5, 10, 0.5)
  2726. expected_ax2 = np.arange(-0.5, 5, 0.5)
  2727. tm.assert_numpy_array_equal(axs[0].get_xticks(), expected_ax1)
  2728. tm.assert_numpy_array_equal(axs[1].get_xticks(), expected_ax2)
  2729. def test_plot_no_rows(self):
  2730. # GH 27758
  2731. df = pd.DataFrame(columns=["foo"], dtype=int)
  2732. assert df.empty
  2733. ax = df.plot()
  2734. assert len(ax.get_lines()) == 1
  2735. line = ax.get_lines()[0]
  2736. assert len(line.get_xdata()) == 0
  2737. assert len(line.get_ydata()) == 0
  2738. def test_plot_no_numeric_data(self):
  2739. df = pd.DataFrame(["a", "b", "c"])
  2740. with pytest.raises(TypeError):
  2741. df.plot()
  2742. def test_missing_markers_legend(self):
  2743. # 14958
  2744. df = pd.DataFrame(np.random.randn(8, 3), columns=["A", "B", "C"])
  2745. ax = df.plot(y=["A"], marker="x", linestyle="solid")
  2746. df.plot(y=["B"], marker="o", linestyle="dotted", ax=ax)
  2747. df.plot(y=["C"], marker="<", linestyle="dotted", ax=ax)
  2748. self._check_legend_labels(ax, labels=["A", "B", "C"])
  2749. self._check_legend_marker(ax, expected_markers=["x", "o", "<"])
  2750. def test_missing_markers_legend_using_style(self):
  2751. # 14563
  2752. df = pd.DataFrame(
  2753. {
  2754. "A": [1, 2, 3, 4, 5, 6],
  2755. "B": [2, 4, 1, 3, 2, 4],
  2756. "C": [3, 3, 2, 6, 4, 2],
  2757. "X": [1, 2, 3, 4, 5, 6],
  2758. }
  2759. )
  2760. fig, ax = self.plt.subplots()
  2761. for kind in "ABC":
  2762. df.plot("X", kind, label=kind, ax=ax, style=".")
  2763. self._check_legend_labels(ax, labels=["A", "B", "C"])
  2764. self._check_legend_marker(ax, expected_markers=[".", ".", "."])
  2765. def _generate_4_axes_via_gridspec():
  2766. import matplotlib.pyplot as plt
  2767. import matplotlib as mpl
  2768. import matplotlib.gridspec # noqa
  2769. gs = mpl.gridspec.GridSpec(2, 2)
  2770. ax_tl = plt.subplot(gs[0, 0])
  2771. ax_ll = plt.subplot(gs[1, 0])
  2772. ax_tr = plt.subplot(gs[0, 1])
  2773. ax_lr = plt.subplot(gs[1, 1])
  2774. return gs, [ax_tl, ax_ll, ax_tr, ax_lr]