test_categorical.py 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906
  1. import numpy as np
  2. import pandas as pd
  3. from scipy import stats, spatial
  4. import matplotlib as mpl
  5. import matplotlib.pyplot as plt
  6. from matplotlib.colors import rgb2hex
  7. from distutils.version import LooseVersion
  8. import pytest
  9. import nose.tools as nt
  10. import numpy.testing as npt
  11. from .. import categorical as cat
  12. from .. import palettes
  13. class CategoricalFixture(object):
  14. """Test boxplot (also base class for things like violinplots)."""
  15. rs = np.random.RandomState(30)
  16. n_total = 60
  17. x = rs.randn(int(n_total / 3), 3)
  18. x_df = pd.DataFrame(x, columns=pd.Series(list("XYZ"), name="big"))
  19. y = pd.Series(rs.randn(n_total), name="y_data")
  20. y_perm = y.reindex(rs.choice(y.index, y.size, replace=False))
  21. g = pd.Series(np.repeat(list("abc"), int(n_total / 3)), name="small")
  22. h = pd.Series(np.tile(list("mn"), int(n_total / 2)), name="medium")
  23. u = pd.Series(np.tile(list("jkh"), int(n_total / 3)))
  24. df = pd.DataFrame(dict(y=y, g=g, h=h, u=u))
  25. x_df["W"] = g
  26. class TestCategoricalPlotter(CategoricalFixture):
  27. def test_wide_df_data(self):
  28. p = cat._CategoricalPlotter()
  29. # Test basic wide DataFrame
  30. p.establish_variables(data=self.x_df)
  31. # Check data attribute
  32. for x, y, in zip(p.plot_data, self.x_df[["X", "Y", "Z"]].values.T):
  33. npt.assert_array_equal(x, y)
  34. # Check semantic attributes
  35. nt.assert_equal(p.orient, "v")
  36. nt.assert_is(p.plot_hues, None)
  37. nt.assert_is(p.group_label, "big")
  38. nt.assert_is(p.value_label, None)
  39. # Test wide dataframe with forced horizontal orientation
  40. p.establish_variables(data=self.x_df, orient="horiz")
  41. nt.assert_equal(p.orient, "h")
  42. # Text exception by trying to hue-group with a wide dataframe
  43. with nt.assert_raises(ValueError):
  44. p.establish_variables(hue="d", data=self.x_df)
  45. def test_1d_input_data(self):
  46. p = cat._CategoricalPlotter()
  47. # Test basic vector data
  48. x_1d_array = self.x.ravel()
  49. p.establish_variables(data=x_1d_array)
  50. nt.assert_equal(len(p.plot_data), 1)
  51. nt.assert_equal(len(p.plot_data[0]), self.n_total)
  52. nt.assert_is(p.group_label, None)
  53. nt.assert_is(p.value_label, None)
  54. # Test basic vector data in list form
  55. x_1d_list = x_1d_array.tolist()
  56. p.establish_variables(data=x_1d_list)
  57. nt.assert_equal(len(p.plot_data), 1)
  58. nt.assert_equal(len(p.plot_data[0]), self.n_total)
  59. nt.assert_is(p.group_label, None)
  60. nt.assert_is(p.value_label, None)
  61. # Test an object array that looks 1D but isn't
  62. x_notreally_1d = np.array([self.x.ravel(),
  63. self.x.ravel()[:int(self.n_total / 2)]])
  64. p.establish_variables(data=x_notreally_1d)
  65. nt.assert_equal(len(p.plot_data), 2)
  66. nt.assert_equal(len(p.plot_data[0]), self.n_total)
  67. nt.assert_equal(len(p.plot_data[1]), self.n_total / 2)
  68. nt.assert_is(p.group_label, None)
  69. nt.assert_is(p.value_label, None)
  70. def test_2d_input_data(self):
  71. p = cat._CategoricalPlotter()
  72. x = self.x[:, 0]
  73. # Test vector data that looks 2D but doesn't really have columns
  74. p.establish_variables(data=x[:, np.newaxis])
  75. nt.assert_equal(len(p.plot_data), 1)
  76. nt.assert_equal(len(p.plot_data[0]), self.x.shape[0])
  77. nt.assert_is(p.group_label, None)
  78. nt.assert_is(p.value_label, None)
  79. # Test vector data that looks 2D but doesn't really have rows
  80. p.establish_variables(data=x[np.newaxis, :])
  81. nt.assert_equal(len(p.plot_data), 1)
  82. nt.assert_equal(len(p.plot_data[0]), self.x.shape[0])
  83. nt.assert_is(p.group_label, None)
  84. nt.assert_is(p.value_label, None)
  85. def test_3d_input_data(self):
  86. p = cat._CategoricalPlotter()
  87. # Test that passing actually 3D data raises
  88. x = np.zeros((5, 5, 5))
  89. with nt.assert_raises(ValueError):
  90. p.establish_variables(data=x)
  91. def test_list_of_array_input_data(self):
  92. p = cat._CategoricalPlotter()
  93. # Test 2D input in list form
  94. x_list = self.x.T.tolist()
  95. p.establish_variables(data=x_list)
  96. nt.assert_equal(len(p.plot_data), 3)
  97. lengths = [len(v_i) for v_i in p.plot_data]
  98. nt.assert_equal(lengths, [self.n_total / 3] * 3)
  99. nt.assert_is(p.group_label, None)
  100. nt.assert_is(p.value_label, None)
  101. def test_wide_array_input_data(self):
  102. p = cat._CategoricalPlotter()
  103. # Test 2D input in array form
  104. p.establish_variables(data=self.x)
  105. nt.assert_equal(np.shape(p.plot_data), (3, self.n_total / 3))
  106. npt.assert_array_equal(p.plot_data, self.x.T)
  107. nt.assert_is(p.group_label, None)
  108. nt.assert_is(p.value_label, None)
  109. def test_single_long_direct_inputs(self):
  110. p = cat._CategoricalPlotter()
  111. # Test passing a series to the x variable
  112. p.establish_variables(x=self.y)
  113. npt.assert_equal(p.plot_data, [self.y])
  114. nt.assert_equal(p.orient, "h")
  115. nt.assert_equal(p.value_label, "y_data")
  116. nt.assert_is(p.group_label, None)
  117. # Test passing a series to the y variable
  118. p.establish_variables(y=self.y)
  119. npt.assert_equal(p.plot_data, [self.y])
  120. nt.assert_equal(p.orient, "v")
  121. nt.assert_equal(p.value_label, "y_data")
  122. nt.assert_is(p.group_label, None)
  123. # Test passing an array to the y variable
  124. p.establish_variables(y=self.y.values)
  125. npt.assert_equal(p.plot_data, [self.y])
  126. nt.assert_equal(p.orient, "v")
  127. nt.assert_is(p.value_label, None)
  128. nt.assert_is(p.group_label, None)
  129. # Test array and series with non-default index
  130. x = pd.Series([1, 1, 1, 1], index=[0, 2, 4, 6])
  131. y = np.array([1, 2, 3, 4])
  132. p.establish_variables(x, y)
  133. assert len(p.plot_data[0]) == 4
  134. def test_single_long_indirect_inputs(self):
  135. p = cat._CategoricalPlotter()
  136. # Test referencing a DataFrame series in the x variable
  137. p.establish_variables(x="y", data=self.df)
  138. npt.assert_equal(p.plot_data, [self.y])
  139. nt.assert_equal(p.orient, "h")
  140. nt.assert_equal(p.value_label, "y")
  141. nt.assert_is(p.group_label, None)
  142. # Test referencing a DataFrame series in the y variable
  143. p.establish_variables(y="y", data=self.df)
  144. npt.assert_equal(p.plot_data, [self.y])
  145. nt.assert_equal(p.orient, "v")
  146. nt.assert_equal(p.value_label, "y")
  147. nt.assert_is(p.group_label, None)
  148. def test_longform_groupby(self):
  149. p = cat._CategoricalPlotter()
  150. # Test a vertically oriented grouped and nested plot
  151. p.establish_variables("g", "y", "h", data=self.df)
  152. nt.assert_equal(len(p.plot_data), 3)
  153. nt.assert_equal(len(p.plot_hues), 3)
  154. nt.assert_equal(p.orient, "v")
  155. nt.assert_equal(p.value_label, "y")
  156. nt.assert_equal(p.group_label, "g")
  157. nt.assert_equal(p.hue_title, "h")
  158. for group, vals in zip(["a", "b", "c"], p.plot_data):
  159. npt.assert_array_equal(vals, self.y[self.g == group])
  160. for group, hues in zip(["a", "b", "c"], p.plot_hues):
  161. npt.assert_array_equal(hues, self.h[self.g == group])
  162. # Test a grouped and nested plot with direct array value data
  163. p.establish_variables("g", self.y.values, "h", self.df)
  164. nt.assert_is(p.value_label, None)
  165. nt.assert_equal(p.group_label, "g")
  166. for group, vals in zip(["a", "b", "c"], p.plot_data):
  167. npt.assert_array_equal(vals, self.y[self.g == group])
  168. # Test a grouped and nested plot with direct array hue data
  169. p.establish_variables("g", "y", self.h.values, self.df)
  170. for group, hues in zip(["a", "b", "c"], p.plot_hues):
  171. npt.assert_array_equal(hues, self.h[self.g == group])
  172. # Test categorical grouping data
  173. df = self.df.copy()
  174. df.g = df.g.astype("category")
  175. # Test that horizontal orientation is automatically detected
  176. p.establish_variables("y", "g", "h", data=df)
  177. nt.assert_equal(len(p.plot_data), 3)
  178. nt.assert_equal(len(p.plot_hues), 3)
  179. nt.assert_equal(p.orient, "h")
  180. nt.assert_equal(p.value_label, "y")
  181. nt.assert_equal(p.group_label, "g")
  182. nt.assert_equal(p.hue_title, "h")
  183. for group, vals in zip(["a", "b", "c"], p.plot_data):
  184. npt.assert_array_equal(vals, self.y[self.g == group])
  185. for group, hues in zip(["a", "b", "c"], p.plot_hues):
  186. npt.assert_array_equal(hues, self.h[self.g == group])
  187. # Test grouped data that matches on index
  188. p1 = cat._CategoricalPlotter()
  189. p1.establish_variables(self.g, self.y, self.h)
  190. p2 = cat._CategoricalPlotter()
  191. p2.establish_variables(self.g, self.y[::-1], self.h)
  192. for i, (d1, d2) in enumerate(zip(p1.plot_data, p2.plot_data)):
  193. assert np.array_equal(d1.sort_index(), d2.sort_index())
  194. def test_input_validation(self):
  195. p = cat._CategoricalPlotter()
  196. kws = dict(x="g", y="y", hue="h", units="u", data=self.df)
  197. for var in ["x", "y", "hue", "units"]:
  198. input_kws = kws.copy()
  199. input_kws[var] = "bad_input"
  200. with nt.assert_raises(ValueError):
  201. p.establish_variables(**input_kws)
  202. def test_order(self):
  203. p = cat._CategoricalPlotter()
  204. # Test inferred order from a wide dataframe input
  205. p.establish_variables(data=self.x_df)
  206. nt.assert_equal(p.group_names, ["X", "Y", "Z"])
  207. # Test specified order with a wide dataframe input
  208. p.establish_variables(data=self.x_df, order=["Y", "Z", "X"])
  209. nt.assert_equal(p.group_names, ["Y", "Z", "X"])
  210. for group, vals in zip(["Y", "Z", "X"], p.plot_data):
  211. npt.assert_array_equal(vals, self.x_df[group])
  212. with nt.assert_raises(ValueError):
  213. p.establish_variables(data=self.x, order=[1, 2, 0])
  214. # Test inferred order from a grouped longform input
  215. p.establish_variables("g", "y", data=self.df)
  216. nt.assert_equal(p.group_names, ["a", "b", "c"])
  217. # Test specified order from a grouped longform input
  218. p.establish_variables("g", "y", data=self.df, order=["b", "a", "c"])
  219. nt.assert_equal(p.group_names, ["b", "a", "c"])
  220. for group, vals in zip(["b", "a", "c"], p.plot_data):
  221. npt.assert_array_equal(vals, self.y[self.g == group])
  222. # Test inferred order from a grouped input with categorical groups
  223. df = self.df.copy()
  224. df.g = df.g.astype("category")
  225. df.g = df.g.cat.reorder_categories(["c", "b", "a"])
  226. p.establish_variables("g", "y", data=df)
  227. nt.assert_equal(p.group_names, ["c", "b", "a"])
  228. for group, vals in zip(["c", "b", "a"], p.plot_data):
  229. npt.assert_array_equal(vals, self.y[self.g == group])
  230. df.g = (df.g.cat.add_categories("d")
  231. .cat.reorder_categories(["c", "b", "d", "a"]))
  232. p.establish_variables("g", "y", data=df)
  233. nt.assert_equal(p.group_names, ["c", "b", "d", "a"])
  234. def test_hue_order(self):
  235. p = cat._CategoricalPlotter()
  236. # Test inferred hue order
  237. p.establish_variables("g", "y", "h", data=self.df)
  238. nt.assert_equal(p.hue_names, ["m", "n"])
  239. # Test specified hue order
  240. p.establish_variables("g", "y", "h", data=self.df,
  241. hue_order=["n", "m"])
  242. nt.assert_equal(p.hue_names, ["n", "m"])
  243. # Test inferred hue order from a categorical hue input
  244. df = self.df.copy()
  245. df.h = df.h.astype("category")
  246. df.h = df.h.cat.reorder_categories(["n", "m"])
  247. p.establish_variables("g", "y", "h", data=df)
  248. nt.assert_equal(p.hue_names, ["n", "m"])
  249. df.h = (df.h.cat.add_categories("o")
  250. .cat.reorder_categories(["o", "m", "n"]))
  251. p.establish_variables("g", "y", "h", data=df)
  252. nt.assert_equal(p.hue_names, ["o", "m", "n"])
  253. def test_plot_units(self):
  254. p = cat._CategoricalPlotter()
  255. p.establish_variables("g", "y", "h", data=self.df)
  256. nt.assert_is(p.plot_units, None)
  257. p.establish_variables("g", "y", "h", data=self.df, units="u")
  258. for group, units in zip(["a", "b", "c"], p.plot_units):
  259. npt.assert_array_equal(units, self.u[self.g == group])
  260. def test_infer_orient(self):
  261. p = cat._CategoricalPlotter()
  262. cats = pd.Series(["a", "b", "c"] * 10)
  263. nums = pd.Series(self.rs.randn(30))
  264. nt.assert_equal(p.infer_orient(cats, nums), "v")
  265. nt.assert_equal(p.infer_orient(nums, cats), "h")
  266. nt.assert_equal(p.infer_orient(nums, None), "h")
  267. nt.assert_equal(p.infer_orient(None, nums), "v")
  268. nt.assert_equal(p.infer_orient(nums, nums, "vert"), "v")
  269. nt.assert_equal(p.infer_orient(nums, nums, "hori"), "h")
  270. with nt.assert_raises(ValueError):
  271. p.infer_orient(cats, cats)
  272. cats = pd.Series([0, 1, 2] * 10, dtype="category")
  273. nt.assert_equal(p.infer_orient(cats, nums), "v")
  274. nt.assert_equal(p.infer_orient(nums, cats), "h")
  275. with nt.assert_raises(ValueError):
  276. p.infer_orient(cats, cats)
  277. def test_default_palettes(self):
  278. p = cat._CategoricalPlotter()
  279. # Test palette mapping the x position
  280. p.establish_variables("g", "y", data=self.df)
  281. p.establish_colors(None, None, 1)
  282. nt.assert_equal(p.colors, palettes.color_palette(n_colors=3))
  283. # Test palette mapping the hue position
  284. p.establish_variables("g", "y", "h", data=self.df)
  285. p.establish_colors(None, None, 1)
  286. nt.assert_equal(p.colors, palettes.color_palette(n_colors=2))
  287. def test_default_palette_with_many_levels(self):
  288. with palettes.color_palette(["blue", "red"], 2):
  289. p = cat._CategoricalPlotter()
  290. p.establish_variables("g", "y", data=self.df)
  291. p.establish_colors(None, None, 1)
  292. npt.assert_array_equal(p.colors,
  293. palettes.husl_palette(3, l=.7)) # noqa
  294. def test_specific_color(self):
  295. p = cat._CategoricalPlotter()
  296. # Test the same color for each x position
  297. p.establish_variables("g", "y", data=self.df)
  298. p.establish_colors("blue", None, 1)
  299. blue_rgb = mpl.colors.colorConverter.to_rgb("blue")
  300. nt.assert_equal(p.colors, [blue_rgb] * 3)
  301. # Test a color-based blend for the hue mapping
  302. p.establish_variables("g", "y", "h", data=self.df)
  303. p.establish_colors("#ff0022", None, 1)
  304. rgba_array = np.array(palettes.light_palette("#ff0022", 2))
  305. npt.assert_array_almost_equal(p.colors,
  306. rgba_array[:, :3])
  307. def test_specific_palette(self):
  308. p = cat._CategoricalPlotter()
  309. # Test palette mapping the x position
  310. p.establish_variables("g", "y", data=self.df)
  311. p.establish_colors(None, "dark", 1)
  312. nt.assert_equal(p.colors, palettes.color_palette("dark", 3))
  313. # Test that non-None `color` and `hue` raises an error
  314. p.establish_variables("g", "y", "h", data=self.df)
  315. p.establish_colors(None, "muted", 1)
  316. nt.assert_equal(p.colors, palettes.color_palette("muted", 2))
  317. # Test that specified palette overrides specified color
  318. p = cat._CategoricalPlotter()
  319. p.establish_variables("g", "y", data=self.df)
  320. p.establish_colors("blue", "deep", 1)
  321. nt.assert_equal(p.colors, palettes.color_palette("deep", 3))
  322. def test_dict_as_palette(self):
  323. p = cat._CategoricalPlotter()
  324. p.establish_variables("g", "y", "h", data=self.df)
  325. pal = {"m": (0, 0, 1), "n": (1, 0, 0)}
  326. p.establish_colors(None, pal, 1)
  327. nt.assert_equal(p.colors, [(0, 0, 1), (1, 0, 0)])
  328. def test_palette_desaturation(self):
  329. p = cat._CategoricalPlotter()
  330. p.establish_variables("g", "y", data=self.df)
  331. p.establish_colors((0, 0, 1), None, .5)
  332. nt.assert_equal(p.colors, [(.25, .25, .75)] * 3)
  333. p.establish_colors(None, [(0, 0, 1), (1, 0, 0), "w"], .5)
  334. nt.assert_equal(p.colors, [(.25, .25, .75),
  335. (.75, .25, .25),
  336. (1, 1, 1)])
  337. class TestCategoricalStatPlotter(CategoricalFixture):
  338. def test_no_bootstrappig(self):
  339. p = cat._CategoricalStatPlotter()
  340. p.establish_variables("g", "y", data=self.df)
  341. p.estimate_statistic(np.mean, None, 100, None)
  342. npt.assert_array_equal(p.confint, np.array([]))
  343. p.establish_variables("g", "y", "h", data=self.df)
  344. p.estimate_statistic(np.mean, None, 100, None)
  345. npt.assert_array_equal(p.confint, np.array([[], [], []]))
  346. def test_single_layer_stats(self):
  347. p = cat._CategoricalStatPlotter()
  348. g = pd.Series(np.repeat(list("abc"), 100))
  349. y = pd.Series(np.random.RandomState(0).randn(300))
  350. p.establish_variables(g, y)
  351. p.estimate_statistic(np.mean, 95, 10000, None)
  352. nt.assert_equal(p.statistic.shape, (3,))
  353. nt.assert_equal(p.confint.shape, (3, 2))
  354. npt.assert_array_almost_equal(p.statistic,
  355. y.groupby(g).mean())
  356. for ci, (_, grp_y) in zip(p.confint, y.groupby(g)):
  357. sem = stats.sem(grp_y)
  358. mean = grp_y.mean()
  359. stats.norm.ppf(.975)
  360. half_ci = stats.norm.ppf(.975) * sem
  361. ci_want = mean - half_ci, mean + half_ci
  362. npt.assert_array_almost_equal(ci_want, ci, 2)
  363. def test_single_layer_stats_with_units(self):
  364. p = cat._CategoricalStatPlotter()
  365. g = pd.Series(np.repeat(list("abc"), 90))
  366. y = pd.Series(np.random.RandomState(0).randn(270))
  367. u = pd.Series(np.repeat(np.tile(list("xyz"), 30), 3))
  368. y[u == "x"] -= 3
  369. y[u == "y"] += 3
  370. p.establish_variables(g, y)
  371. p.estimate_statistic(np.mean, 95, 10000, None)
  372. stat1, ci1 = p.statistic, p.confint
  373. p.establish_variables(g, y, units=u)
  374. p.estimate_statistic(np.mean, 95, 10000, None)
  375. stat2, ci2 = p.statistic, p.confint
  376. npt.assert_array_equal(stat1, stat2)
  377. ci1_size = ci1[:, 1] - ci1[:, 0]
  378. ci2_size = ci2[:, 1] - ci2[:, 0]
  379. npt.assert_array_less(ci1_size, ci2_size)
  380. def test_single_layer_stats_with_missing_data(self):
  381. p = cat._CategoricalStatPlotter()
  382. g = pd.Series(np.repeat(list("abc"), 100))
  383. y = pd.Series(np.random.RandomState(0).randn(300))
  384. p.establish_variables(g, y, order=list("abdc"))
  385. p.estimate_statistic(np.mean, 95, 10000, None)
  386. nt.assert_equal(p.statistic.shape, (4,))
  387. nt.assert_equal(p.confint.shape, (4, 2))
  388. mean = y[g == "b"].mean()
  389. sem = stats.sem(y[g == "b"])
  390. half_ci = stats.norm.ppf(.975) * sem
  391. ci = mean - half_ci, mean + half_ci
  392. npt.assert_almost_equal(p.statistic[1], mean)
  393. npt.assert_array_almost_equal(p.confint[1], ci, 2)
  394. npt.assert_equal(p.statistic[2], np.nan)
  395. npt.assert_array_equal(p.confint[2], (np.nan, np.nan))
  396. def test_nested_stats(self):
  397. p = cat._CategoricalStatPlotter()
  398. g = pd.Series(np.repeat(list("abc"), 100))
  399. h = pd.Series(np.tile(list("xy"), 150))
  400. y = pd.Series(np.random.RandomState(0).randn(300))
  401. p.establish_variables(g, y, h)
  402. p.estimate_statistic(np.mean, 95, 50000, None)
  403. nt.assert_equal(p.statistic.shape, (3, 2))
  404. nt.assert_equal(p.confint.shape, (3, 2, 2))
  405. npt.assert_array_almost_equal(p.statistic,
  406. y.groupby([g, h]).mean().unstack())
  407. for ci_g, (_, grp_y) in zip(p.confint, y.groupby(g)):
  408. for ci, hue_y in zip(ci_g, [grp_y[::2], grp_y[1::2]]):
  409. sem = stats.sem(hue_y)
  410. mean = hue_y.mean()
  411. half_ci = stats.norm.ppf(.975) * sem
  412. ci_want = mean - half_ci, mean + half_ci
  413. npt.assert_array_almost_equal(ci_want, ci, 2)
  414. def test_bootstrap_seed(self):
  415. p = cat._CategoricalStatPlotter()
  416. g = pd.Series(np.repeat(list("abc"), 100))
  417. h = pd.Series(np.tile(list("xy"), 150))
  418. y = pd.Series(np.random.RandomState(0).randn(300))
  419. p.establish_variables(g, y, h)
  420. p.estimate_statistic(np.mean, 95, 1000, 0)
  421. confint_1 = p.confint
  422. p.estimate_statistic(np.mean, 95, 1000, 0)
  423. confint_2 = p.confint
  424. npt.assert_array_equal(confint_1, confint_2)
  425. def test_nested_stats_with_units(self):
  426. p = cat._CategoricalStatPlotter()
  427. g = pd.Series(np.repeat(list("abc"), 90))
  428. h = pd.Series(np.tile(list("xy"), 135))
  429. u = pd.Series(np.repeat(list("ijkijk"), 45))
  430. y = pd.Series(np.random.RandomState(0).randn(270))
  431. y[u == "i"] -= 3
  432. y[u == "k"] += 3
  433. p.establish_variables(g, y, h)
  434. p.estimate_statistic(np.mean, 95, 10000, None)
  435. stat1, ci1 = p.statistic, p.confint
  436. p.establish_variables(g, y, h, units=u)
  437. p.estimate_statistic(np.mean, 95, 10000, None)
  438. stat2, ci2 = p.statistic, p.confint
  439. npt.assert_array_equal(stat1, stat2)
  440. ci1_size = ci1[:, 0, 1] - ci1[:, 0, 0]
  441. ci2_size = ci2[:, 0, 1] - ci2[:, 0, 0]
  442. npt.assert_array_less(ci1_size, ci2_size)
  443. def test_nested_stats_with_missing_data(self):
  444. p = cat._CategoricalStatPlotter()
  445. g = pd.Series(np.repeat(list("abc"), 100))
  446. y = pd.Series(np.random.RandomState(0).randn(300))
  447. h = pd.Series(np.tile(list("xy"), 150))
  448. p.establish_variables(g, y, h,
  449. order=list("abdc"),
  450. hue_order=list("zyx"))
  451. p.estimate_statistic(np.mean, 95, 50000, None)
  452. nt.assert_equal(p.statistic.shape, (4, 3))
  453. nt.assert_equal(p.confint.shape, (4, 3, 2))
  454. mean = y[(g == "b") & (h == "x")].mean()
  455. sem = stats.sem(y[(g == "b") & (h == "x")])
  456. half_ci = stats.norm.ppf(.975) * sem
  457. ci = mean - half_ci, mean + half_ci
  458. npt.assert_almost_equal(p.statistic[1, 2], mean)
  459. npt.assert_array_almost_equal(p.confint[1, 2], ci, 2)
  460. npt.assert_array_equal(p.statistic[:, 0], [np.nan] * 4)
  461. npt.assert_array_equal(p.statistic[2], [np.nan] * 3)
  462. npt.assert_array_equal(p.confint[:, 0],
  463. np.zeros((4, 2)) * np.nan)
  464. npt.assert_array_equal(p.confint[2],
  465. np.zeros((3, 2)) * np.nan)
  466. def test_sd_error_bars(self):
  467. p = cat._CategoricalStatPlotter()
  468. g = pd.Series(np.repeat(list("abc"), 100))
  469. y = pd.Series(np.random.RandomState(0).randn(300))
  470. p.establish_variables(g, y)
  471. p.estimate_statistic(np.mean, "sd", None, None)
  472. nt.assert_equal(p.statistic.shape, (3,))
  473. nt.assert_equal(p.confint.shape, (3, 2))
  474. npt.assert_array_almost_equal(p.statistic,
  475. y.groupby(g).mean())
  476. for ci, (_, grp_y) in zip(p.confint, y.groupby(g)):
  477. mean = grp_y.mean()
  478. half_ci = np.std(grp_y)
  479. ci_want = mean - half_ci, mean + half_ci
  480. npt.assert_array_almost_equal(ci_want, ci, 2)
  481. def test_nested_sd_error_bars(self):
  482. p = cat._CategoricalStatPlotter()
  483. g = pd.Series(np.repeat(list("abc"), 100))
  484. h = pd.Series(np.tile(list("xy"), 150))
  485. y = pd.Series(np.random.RandomState(0).randn(300))
  486. p.establish_variables(g, y, h)
  487. p.estimate_statistic(np.mean, "sd", None, None)
  488. nt.assert_equal(p.statistic.shape, (3, 2))
  489. nt.assert_equal(p.confint.shape, (3, 2, 2))
  490. npt.assert_array_almost_equal(p.statistic,
  491. y.groupby([g, h]).mean().unstack())
  492. for ci_g, (_, grp_y) in zip(p.confint, y.groupby(g)):
  493. for ci, hue_y in zip(ci_g, [grp_y[::2], grp_y[1::2]]):
  494. mean = hue_y.mean()
  495. half_ci = np.std(hue_y)
  496. ci_want = mean - half_ci, mean + half_ci
  497. npt.assert_array_almost_equal(ci_want, ci, 2)
  498. def test_draw_cis(self):
  499. p = cat._CategoricalStatPlotter()
  500. # Test vertical CIs
  501. p.orient = "v"
  502. f, ax = plt.subplots()
  503. at_group = [0, 1]
  504. confints = [(.5, 1.5), (.25, .8)]
  505. colors = [".2", ".3"]
  506. p.draw_confints(ax, at_group, confints, colors)
  507. lines = ax.lines
  508. for line, at, ci, c in zip(lines, at_group, confints, colors):
  509. x, y = line.get_xydata().T
  510. npt.assert_array_equal(x, [at, at])
  511. npt.assert_array_equal(y, ci)
  512. nt.assert_equal(line.get_color(), c)
  513. plt.close("all")
  514. # Test horizontal CIs
  515. p.orient = "h"
  516. f, ax = plt.subplots()
  517. p.draw_confints(ax, at_group, confints, colors)
  518. lines = ax.lines
  519. for line, at, ci, c in zip(lines, at_group, confints, colors):
  520. x, y = line.get_xydata().T
  521. npt.assert_array_equal(x, ci)
  522. npt.assert_array_equal(y, [at, at])
  523. nt.assert_equal(line.get_color(), c)
  524. plt.close("all")
  525. # Test vertical CIs with endcaps
  526. p.orient = "v"
  527. f, ax = plt.subplots()
  528. p.draw_confints(ax, at_group, confints, colors, capsize=0.3)
  529. capline = ax.lines[len(ax.lines) - 1]
  530. caplinestart = capline.get_xdata()[0]
  531. caplineend = capline.get_xdata()[1]
  532. caplinelength = abs(caplineend - caplinestart)
  533. nt.assert_almost_equal(caplinelength, 0.3)
  534. nt.assert_equal(len(ax.lines), 6)
  535. plt.close("all")
  536. # Test horizontal CIs with endcaps
  537. p.orient = "h"
  538. f, ax = plt.subplots()
  539. p.draw_confints(ax, at_group, confints, colors, capsize=0.3)
  540. capline = ax.lines[len(ax.lines) - 1]
  541. caplinestart = capline.get_ydata()[0]
  542. caplineend = capline.get_ydata()[1]
  543. caplinelength = abs(caplineend - caplinestart)
  544. nt.assert_almost_equal(caplinelength, 0.3)
  545. nt.assert_equal(len(ax.lines), 6)
  546. # Test extra keyword arguments
  547. f, ax = plt.subplots()
  548. p.draw_confints(ax, at_group, confints, colors, lw=4)
  549. line = ax.lines[0]
  550. nt.assert_equal(line.get_linewidth(), 4)
  551. plt.close("all")
  552. # Test errwidth is set appropriately
  553. f, ax = plt.subplots()
  554. p.draw_confints(ax, at_group, confints, colors, errwidth=2)
  555. capline = ax.lines[len(ax.lines)-1]
  556. nt.assert_equal(capline._linewidth, 2)
  557. nt.assert_equal(len(ax.lines), 2)
  558. plt.close("all")
  559. class TestBoxPlotter(CategoricalFixture):
  560. default_kws = dict(x=None, y=None, hue=None, data=None,
  561. order=None, hue_order=None,
  562. orient=None, color=None, palette=None,
  563. saturation=.75, width=.8, dodge=True,
  564. fliersize=5, linewidth=None)
  565. def test_nested_width(self):
  566. kws = self.default_kws.copy()
  567. p = cat._BoxPlotter(**kws)
  568. p.establish_variables("g", "y", "h", data=self.df)
  569. nt.assert_equal(p.nested_width, .4 * .98)
  570. kws = self.default_kws.copy()
  571. kws["width"] = .6
  572. p = cat._BoxPlotter(**kws)
  573. p.establish_variables("g", "y", "h", data=self.df)
  574. nt.assert_equal(p.nested_width, .3 * .98)
  575. kws = self.default_kws.copy()
  576. kws["dodge"] = False
  577. p = cat._BoxPlotter(**kws)
  578. p.establish_variables("g", "y", "h", data=self.df)
  579. nt.assert_equal(p.nested_width, .8)
  580. def test_hue_offsets(self):
  581. p = cat._BoxPlotter(**self.default_kws)
  582. p.establish_variables("g", "y", "h", data=self.df)
  583. npt.assert_array_equal(p.hue_offsets, [-.2, .2])
  584. kws = self.default_kws.copy()
  585. kws["width"] = .6
  586. p = cat._BoxPlotter(**kws)
  587. p.establish_variables("g", "y", "h", data=self.df)
  588. npt.assert_array_equal(p.hue_offsets, [-.15, .15])
  589. p = cat._BoxPlotter(**kws)
  590. p.establish_variables("h", "y", "g", data=self.df)
  591. npt.assert_array_almost_equal(p.hue_offsets, [-.2, 0, .2])
  592. def test_axes_data(self):
  593. ax = cat.boxplot("g", "y", data=self.df)
  594. nt.assert_equal(len(ax.artists), 3)
  595. plt.close("all")
  596. ax = cat.boxplot("g", "y", "h", data=self.df)
  597. nt.assert_equal(len(ax.artists), 6)
  598. plt.close("all")
  599. def test_box_colors(self):
  600. ax = cat.boxplot("g", "y", data=self.df, saturation=1)
  601. pal = palettes.color_palette(n_colors=3)
  602. for patch, color in zip(ax.artists, pal):
  603. nt.assert_equal(patch.get_facecolor()[:3], color)
  604. plt.close("all")
  605. ax = cat.boxplot("g", "y", "h", data=self.df, saturation=1)
  606. pal = palettes.color_palette(n_colors=2)
  607. for patch, color in zip(ax.artists, pal * 2):
  608. nt.assert_equal(patch.get_facecolor()[:3], color)
  609. plt.close("all")
  610. def test_draw_missing_boxes(self):
  611. ax = cat.boxplot("g", "y", data=self.df,
  612. order=["a", "b", "c", "d"])
  613. nt.assert_equal(len(ax.artists), 3)
  614. def test_missing_data(self):
  615. x = ["a", "a", "b", "b", "c", "c", "d", "d"]
  616. h = ["x", "y", "x", "y", "x", "y", "x", "y"]
  617. y = self.rs.randn(8)
  618. y[-2:] = np.nan
  619. ax = cat.boxplot(x, y)
  620. nt.assert_equal(len(ax.artists), 3)
  621. plt.close("all")
  622. y[-1] = 0
  623. ax = cat.boxplot(x, y, h)
  624. nt.assert_equal(len(ax.artists), 7)
  625. plt.close("all")
  626. def test_unaligned_index(self):
  627. f, (ax1, ax2) = plt.subplots(2)
  628. cat.boxplot(self.g, self.y, ax=ax1)
  629. cat.boxplot(self.g, self.y_perm, ax=ax2)
  630. for l1, l2 in zip(ax1.lines, ax2.lines):
  631. assert np.array_equal(l1.get_xydata(), l2.get_xydata())
  632. f, (ax1, ax2) = plt.subplots(2)
  633. hue_order = self.h.unique()
  634. cat.boxplot(self.g, self.y, self.h, hue_order=hue_order, ax=ax1)
  635. cat.boxplot(self.g, self.y_perm, self.h,
  636. hue_order=hue_order, ax=ax2)
  637. for l1, l2 in zip(ax1.lines, ax2.lines):
  638. assert np.array_equal(l1.get_xydata(), l2.get_xydata())
  639. def test_boxplots(self):
  640. # Smoke test the high level boxplot options
  641. cat.boxplot("y", data=self.df)
  642. plt.close("all")
  643. cat.boxplot(y="y", data=self.df)
  644. plt.close("all")
  645. cat.boxplot("g", "y", data=self.df)
  646. plt.close("all")
  647. cat.boxplot("y", "g", data=self.df, orient="h")
  648. plt.close("all")
  649. cat.boxplot("g", "y", "h", data=self.df)
  650. plt.close("all")
  651. cat.boxplot("g", "y", "h", order=list("nabc"), data=self.df)
  652. plt.close("all")
  653. cat.boxplot("g", "y", "h", hue_order=list("omn"), data=self.df)
  654. plt.close("all")
  655. cat.boxplot("y", "g", "h", data=self.df, orient="h")
  656. plt.close("all")
  657. def test_axes_annotation(self):
  658. ax = cat.boxplot("g", "y", data=self.df)
  659. nt.assert_equal(ax.get_xlabel(), "g")
  660. nt.assert_equal(ax.get_ylabel(), "y")
  661. nt.assert_equal(ax.get_xlim(), (-.5, 2.5))
  662. npt.assert_array_equal(ax.get_xticks(), [0, 1, 2])
  663. npt.assert_array_equal([l.get_text() for l in ax.get_xticklabels()],
  664. ["a", "b", "c"])
  665. plt.close("all")
  666. ax = cat.boxplot("g", "y", "h", data=self.df)
  667. nt.assert_equal(ax.get_xlabel(), "g")
  668. nt.assert_equal(ax.get_ylabel(), "y")
  669. npt.assert_array_equal(ax.get_xticks(), [0, 1, 2])
  670. npt.assert_array_equal([l.get_text() for l in ax.get_xticklabels()],
  671. ["a", "b", "c"])
  672. npt.assert_array_equal([l.get_text() for l in ax.legend_.get_texts()],
  673. ["m", "n"])
  674. plt.close("all")
  675. ax = cat.boxplot("y", "g", data=self.df, orient="h")
  676. nt.assert_equal(ax.get_xlabel(), "y")
  677. nt.assert_equal(ax.get_ylabel(), "g")
  678. nt.assert_equal(ax.get_ylim(), (2.5, -.5))
  679. npt.assert_array_equal(ax.get_yticks(), [0, 1, 2])
  680. npt.assert_array_equal([l.get_text() for l in ax.get_yticklabels()],
  681. ["a", "b", "c"])
  682. plt.close("all")
  683. class TestViolinPlotter(CategoricalFixture):
  684. default_kws = dict(x=None, y=None, hue=None, data=None,
  685. order=None, hue_order=None,
  686. bw="scott", cut=2, scale="area", scale_hue=True,
  687. gridsize=100, width=.8, inner="box", split=False,
  688. dodge=True, orient=None, linewidth=None,
  689. color=None, palette=None, saturation=.75)
  690. def test_split_error(self):
  691. kws = self.default_kws.copy()
  692. kws.update(dict(x="h", y="y", hue="g", data=self.df, split=True))
  693. with nt.assert_raises(ValueError):
  694. cat._ViolinPlotter(**kws)
  695. def test_no_observations(self):
  696. p = cat._ViolinPlotter(**self.default_kws)
  697. x = ["a", "a", "b"]
  698. y = self.rs.randn(3)
  699. y[-1] = np.nan
  700. p.establish_variables(x, y)
  701. p.estimate_densities("scott", 2, "area", True, 20)
  702. nt.assert_equal(len(p.support[0]), 20)
  703. nt.assert_equal(len(p.support[1]), 0)
  704. nt.assert_equal(len(p.density[0]), 20)
  705. nt.assert_equal(len(p.density[1]), 1)
  706. nt.assert_equal(p.density[1].item(), 1)
  707. p.estimate_densities("scott", 2, "count", True, 20)
  708. nt.assert_equal(p.density[1].item(), 0)
  709. x = ["a"] * 4 + ["b"] * 2
  710. y = self.rs.randn(6)
  711. h = ["m", "n"] * 2 + ["m"] * 2
  712. p.establish_variables(x, y, h)
  713. p.estimate_densities("scott", 2, "area", True, 20)
  714. nt.assert_equal(len(p.support[1][0]), 20)
  715. nt.assert_equal(len(p.support[1][1]), 0)
  716. nt.assert_equal(len(p.density[1][0]), 20)
  717. nt.assert_equal(len(p.density[1][1]), 1)
  718. nt.assert_equal(p.density[1][1].item(), 1)
  719. p.estimate_densities("scott", 2, "count", False, 20)
  720. nt.assert_equal(p.density[1][1].item(), 0)
  721. def test_single_observation(self):
  722. p = cat._ViolinPlotter(**self.default_kws)
  723. x = ["a", "a", "b"]
  724. y = self.rs.randn(3)
  725. p.establish_variables(x, y)
  726. p.estimate_densities("scott", 2, "area", True, 20)
  727. nt.assert_equal(len(p.support[0]), 20)
  728. nt.assert_equal(len(p.support[1]), 1)
  729. nt.assert_equal(len(p.density[0]), 20)
  730. nt.assert_equal(len(p.density[1]), 1)
  731. nt.assert_equal(p.density[1].item(), 1)
  732. p.estimate_densities("scott", 2, "count", True, 20)
  733. nt.assert_equal(p.density[1].item(), .5)
  734. x = ["b"] * 4 + ["a"] * 3
  735. y = self.rs.randn(7)
  736. h = (["m", "n"] * 4)[:-1]
  737. p.establish_variables(x, y, h)
  738. p.estimate_densities("scott", 2, "area", True, 20)
  739. nt.assert_equal(len(p.support[1][0]), 20)
  740. nt.assert_equal(len(p.support[1][1]), 1)
  741. nt.assert_equal(len(p.density[1][0]), 20)
  742. nt.assert_equal(len(p.density[1][1]), 1)
  743. nt.assert_equal(p.density[1][1].item(), 1)
  744. p.estimate_densities("scott", 2, "count", False, 20)
  745. nt.assert_equal(p.density[1][1].item(), .5)
  746. def test_dwidth(self):
  747. kws = self.default_kws.copy()
  748. kws.update(dict(x="g", y="y", data=self.df))
  749. p = cat._ViolinPlotter(**kws)
  750. nt.assert_equal(p.dwidth, .4)
  751. kws.update(dict(width=.4))
  752. p = cat._ViolinPlotter(**kws)
  753. nt.assert_equal(p.dwidth, .2)
  754. kws.update(dict(hue="h", width=.8))
  755. p = cat._ViolinPlotter(**kws)
  756. nt.assert_equal(p.dwidth, .2)
  757. kws.update(dict(split=True))
  758. p = cat._ViolinPlotter(**kws)
  759. nt.assert_equal(p.dwidth, .4)
  760. def test_scale_area(self):
  761. kws = self.default_kws.copy()
  762. kws["scale"] = "area"
  763. p = cat._ViolinPlotter(**kws)
  764. # Test single layer of grouping
  765. p.hue_names = None
  766. density = [self.rs.uniform(0, .8, 50), self.rs.uniform(0, .2, 50)]
  767. max_before = np.array([d.max() for d in density])
  768. p.scale_area(density, max_before, False)
  769. max_after = np.array([d.max() for d in density])
  770. nt.assert_equal(max_after[0], 1)
  771. before_ratio = max_before[1] / max_before[0]
  772. after_ratio = max_after[1] / max_after[0]
  773. nt.assert_equal(before_ratio, after_ratio)
  774. # Test nested grouping scaling across all densities
  775. p.hue_names = ["foo", "bar"]
  776. density = [[self.rs.uniform(0, .8, 50), self.rs.uniform(0, .2, 50)],
  777. [self.rs.uniform(0, .1, 50), self.rs.uniform(0, .02, 50)]]
  778. max_before = np.array([[r.max() for r in row] for row in density])
  779. p.scale_area(density, max_before, False)
  780. max_after = np.array([[r.max() for r in row] for row in density])
  781. nt.assert_equal(max_after[0, 0], 1)
  782. before_ratio = max_before[1, 1] / max_before[0, 0]
  783. after_ratio = max_after[1, 1] / max_after[0, 0]
  784. nt.assert_equal(before_ratio, after_ratio)
  785. # Test nested grouping scaling within hue
  786. p.hue_names = ["foo", "bar"]
  787. density = [[self.rs.uniform(0, .8, 50), self.rs.uniform(0, .2, 50)],
  788. [self.rs.uniform(0, .1, 50), self.rs.uniform(0, .02, 50)]]
  789. max_before = np.array([[r.max() for r in row] for row in density])
  790. p.scale_area(density, max_before, True)
  791. max_after = np.array([[r.max() for r in row] for row in density])
  792. nt.assert_equal(max_after[0, 0], 1)
  793. nt.assert_equal(max_after[1, 0], 1)
  794. before_ratio = max_before[1, 1] / max_before[1, 0]
  795. after_ratio = max_after[1, 1] / max_after[1, 0]
  796. nt.assert_equal(before_ratio, after_ratio)
  797. def test_scale_width(self):
  798. kws = self.default_kws.copy()
  799. kws["scale"] = "width"
  800. p = cat._ViolinPlotter(**kws)
  801. # Test single layer of grouping
  802. p.hue_names = None
  803. density = [self.rs.uniform(0, .8, 50), self.rs.uniform(0, .2, 50)]
  804. p.scale_width(density)
  805. max_after = np.array([d.max() for d in density])
  806. npt.assert_array_equal(max_after, [1, 1])
  807. # Test nested grouping
  808. p.hue_names = ["foo", "bar"]
  809. density = [[self.rs.uniform(0, .8, 50), self.rs.uniform(0, .2, 50)],
  810. [self.rs.uniform(0, .1, 50), self.rs.uniform(0, .02, 50)]]
  811. p.scale_width(density)
  812. max_after = np.array([[r.max() for r in row] for row in density])
  813. npt.assert_array_equal(max_after, [[1, 1], [1, 1]])
  814. def test_scale_count(self):
  815. kws = self.default_kws.copy()
  816. kws["scale"] = "count"
  817. p = cat._ViolinPlotter(**kws)
  818. # Test single layer of grouping
  819. p.hue_names = None
  820. density = [self.rs.uniform(0, .8, 20), self.rs.uniform(0, .2, 40)]
  821. counts = np.array([20, 40])
  822. p.scale_count(density, counts, False)
  823. max_after = np.array([d.max() for d in density])
  824. npt.assert_array_equal(max_after, [.5, 1])
  825. # Test nested grouping scaling across all densities
  826. p.hue_names = ["foo", "bar"]
  827. density = [[self.rs.uniform(0, .8, 5), self.rs.uniform(0, .2, 40)],
  828. [self.rs.uniform(0, .1, 100), self.rs.uniform(0, .02, 50)]]
  829. counts = np.array([[5, 40], [100, 50]])
  830. p.scale_count(density, counts, False)
  831. max_after = np.array([[r.max() for r in row] for row in density])
  832. npt.assert_array_equal(max_after, [[.05, .4], [1, .5]])
  833. # Test nested grouping scaling within hue
  834. p.hue_names = ["foo", "bar"]
  835. density = [[self.rs.uniform(0, .8, 5), self.rs.uniform(0, .2, 40)],
  836. [self.rs.uniform(0, .1, 100), self.rs.uniform(0, .02, 50)]]
  837. counts = np.array([[5, 40], [100, 50]])
  838. p.scale_count(density, counts, True)
  839. max_after = np.array([[r.max() for r in row] for row in density])
  840. npt.assert_array_equal(max_after, [[.125, 1], [1, .5]])
  841. def test_bad_scale(self):
  842. kws = self.default_kws.copy()
  843. kws["scale"] = "not_a_scale_type"
  844. with nt.assert_raises(ValueError):
  845. cat._ViolinPlotter(**kws)
  846. def test_kde_fit(self):
  847. p = cat._ViolinPlotter(**self.default_kws)
  848. data = self.y
  849. data_std = data.std(ddof=1)
  850. # Test reference rule bandwidth
  851. kde, bw = p.fit_kde(data, "scott")
  852. nt.assert_is_instance(kde, stats.gaussian_kde)
  853. nt.assert_equal(kde.factor, kde.scotts_factor())
  854. nt.assert_equal(bw, kde.scotts_factor() * data_std)
  855. # Test numeric scale factor
  856. kde, bw = p.fit_kde(self.y, .2)
  857. nt.assert_is_instance(kde, stats.gaussian_kde)
  858. nt.assert_equal(kde.factor, .2)
  859. nt.assert_equal(bw, .2 * data_std)
  860. def test_draw_to_density(self):
  861. p = cat._ViolinPlotter(**self.default_kws)
  862. # p.dwidth will be 1 for easier testing
  863. p.width = 2
  864. # Test verical plots
  865. support = np.array([.2, .6])
  866. density = np.array([.1, .4])
  867. # Test full vertical plot
  868. _, ax = plt.subplots()
  869. p.draw_to_density(ax, 0, .5, support, density, False)
  870. x, y = ax.lines[0].get_xydata().T
  871. npt.assert_array_equal(x, [.99 * -.4, .99 * .4])
  872. npt.assert_array_equal(y, [.5, .5])
  873. plt.close("all")
  874. # Test left vertical plot
  875. _, ax = plt.subplots()
  876. p.draw_to_density(ax, 0, .5, support, density, "left")
  877. x, y = ax.lines[0].get_xydata().T
  878. npt.assert_array_equal(x, [.99 * -.4, 0])
  879. npt.assert_array_equal(y, [.5, .5])
  880. plt.close("all")
  881. # Test right vertical plot
  882. _, ax = plt.subplots()
  883. p.draw_to_density(ax, 0, .5, support, density, "right")
  884. x, y = ax.lines[0].get_xydata().T
  885. npt.assert_array_equal(x, [0, .99 * .4])
  886. npt.assert_array_equal(y, [.5, .5])
  887. plt.close("all")
  888. # Switch orientation to test horizontal plots
  889. p.orient = "h"
  890. support = np.array([.2, .5])
  891. density = np.array([.3, .7])
  892. # Test full horizontal plot
  893. _, ax = plt.subplots()
  894. p.draw_to_density(ax, 0, .6, support, density, False)
  895. x, y = ax.lines[0].get_xydata().T
  896. npt.assert_array_equal(x, [.6, .6])
  897. npt.assert_array_equal(y, [.99 * -.7, .99 * .7])
  898. plt.close("all")
  899. # Test left horizontal plot
  900. _, ax = plt.subplots()
  901. p.draw_to_density(ax, 0, .6, support, density, "left")
  902. x, y = ax.lines[0].get_xydata().T
  903. npt.assert_array_equal(x, [.6, .6])
  904. npt.assert_array_equal(y, [.99 * -.7, 0])
  905. plt.close("all")
  906. # Test right horizontal plot
  907. _, ax = plt.subplots()
  908. p.draw_to_density(ax, 0, .6, support, density, "right")
  909. x, y = ax.lines[0].get_xydata().T
  910. npt.assert_array_equal(x, [.6, .6])
  911. npt.assert_array_equal(y, [0, .99 * .7])
  912. plt.close("all")
  913. def test_draw_single_observations(self):
  914. p = cat._ViolinPlotter(**self.default_kws)
  915. p.width = 2
  916. # Test vertical plot
  917. _, ax = plt.subplots()
  918. p.draw_single_observation(ax, 1, 1.5, 1)
  919. x, y = ax.lines[0].get_xydata().T
  920. npt.assert_array_equal(x, [0, 2])
  921. npt.assert_array_equal(y, [1.5, 1.5])
  922. plt.close("all")
  923. # Test horizontal plot
  924. p.orient = "h"
  925. _, ax = plt.subplots()
  926. p.draw_single_observation(ax, 2, 2.2, .5)
  927. x, y = ax.lines[0].get_xydata().T
  928. npt.assert_array_equal(x, [2.2, 2.2])
  929. npt.assert_array_equal(y, [1.5, 2.5])
  930. plt.close("all")
  931. def test_draw_box_lines(self):
  932. # Test vertical plot
  933. kws = self.default_kws.copy()
  934. kws.update(dict(y="y", data=self.df, inner=None))
  935. p = cat._ViolinPlotter(**kws)
  936. _, ax = plt.subplots()
  937. p.draw_box_lines(ax, self.y, p.support[0], p.density[0], 0)
  938. nt.assert_equal(len(ax.lines), 2)
  939. q25, q50, q75 = np.percentile(self.y, [25, 50, 75])
  940. _, y = ax.lines[1].get_xydata().T
  941. npt.assert_array_equal(y, [q25, q75])
  942. _, y = ax.collections[0].get_offsets().T
  943. nt.assert_equal(y, q50)
  944. plt.close("all")
  945. # Test horizontal plot
  946. kws = self.default_kws.copy()
  947. kws.update(dict(x="y", data=self.df, inner=None))
  948. p = cat._ViolinPlotter(**kws)
  949. _, ax = plt.subplots()
  950. p.draw_box_lines(ax, self.y, p.support[0], p.density[0], 0)
  951. nt.assert_equal(len(ax.lines), 2)
  952. q25, q50, q75 = np.percentile(self.y, [25, 50, 75])
  953. x, _ = ax.lines[1].get_xydata().T
  954. npt.assert_array_equal(x, [q25, q75])
  955. x, _ = ax.collections[0].get_offsets().T
  956. nt.assert_equal(x, q50)
  957. plt.close("all")
  958. def test_draw_quartiles(self):
  959. kws = self.default_kws.copy()
  960. kws.update(dict(y="y", data=self.df, inner=None))
  961. p = cat._ViolinPlotter(**kws)
  962. _, ax = plt.subplots()
  963. p.draw_quartiles(ax, self.y, p.support[0], p.density[0], 0)
  964. for val, line in zip(np.percentile(self.y, [25, 50, 75]), ax.lines):
  965. _, y = line.get_xydata().T
  966. npt.assert_array_equal(y, [val, val])
  967. def test_draw_points(self):
  968. p = cat._ViolinPlotter(**self.default_kws)
  969. # Test vertical plot
  970. _, ax = plt.subplots()
  971. p.draw_points(ax, self.y, 0)
  972. x, y = ax.collections[0].get_offsets().T
  973. npt.assert_array_equal(x, np.zeros_like(self.y))
  974. npt.assert_array_equal(y, self.y)
  975. plt.close("all")
  976. # Test horizontal plot
  977. p.orient = "h"
  978. _, ax = plt.subplots()
  979. p.draw_points(ax, self.y, 0)
  980. x, y = ax.collections[0].get_offsets().T
  981. npt.assert_array_equal(x, self.y)
  982. npt.assert_array_equal(y, np.zeros_like(self.y))
  983. plt.close("all")
  984. def test_draw_sticks(self):
  985. kws = self.default_kws.copy()
  986. kws.update(dict(y="y", data=self.df, inner=None))
  987. p = cat._ViolinPlotter(**kws)
  988. # Test vertical plot
  989. _, ax = plt.subplots()
  990. p.draw_stick_lines(ax, self.y, p.support[0], p.density[0], 0)
  991. for val, line in zip(self.y, ax.lines):
  992. _, y = line.get_xydata().T
  993. npt.assert_array_equal(y, [val, val])
  994. plt.close("all")
  995. # Test horizontal plot
  996. p.orient = "h"
  997. _, ax = plt.subplots()
  998. p.draw_stick_lines(ax, self.y, p.support[0], p.density[0], 0)
  999. for val, line in zip(self.y, ax.lines):
  1000. x, _ = line.get_xydata().T
  1001. npt.assert_array_equal(x, [val, val])
  1002. plt.close("all")
  1003. def test_validate_inner(self):
  1004. kws = self.default_kws.copy()
  1005. kws.update(dict(inner="bad_inner"))
  1006. with nt.assert_raises(ValueError):
  1007. cat._ViolinPlotter(**kws)
  1008. def test_draw_violinplots(self):
  1009. kws = self.default_kws.copy()
  1010. # Test single vertical violin
  1011. kws.update(dict(y="y", data=self.df, inner=None,
  1012. saturation=1, color=(1, 0, 0, 1)))
  1013. p = cat._ViolinPlotter(**kws)
  1014. _, ax = plt.subplots()
  1015. p.draw_violins(ax)
  1016. nt.assert_equal(len(ax.collections), 1)
  1017. npt.assert_array_equal(ax.collections[0].get_facecolors(),
  1018. [(1, 0, 0, 1)])
  1019. plt.close("all")
  1020. # Test single horizontal violin
  1021. kws.update(dict(x="y", y=None, color=(0, 1, 0, 1)))
  1022. p = cat._ViolinPlotter(**kws)
  1023. _, ax = plt.subplots()
  1024. p.draw_violins(ax)
  1025. nt.assert_equal(len(ax.collections), 1)
  1026. npt.assert_array_equal(ax.collections[0].get_facecolors(),
  1027. [(0, 1, 0, 1)])
  1028. plt.close("all")
  1029. # Test multiple vertical violins
  1030. kws.update(dict(x="g", y="y", color=None,))
  1031. p = cat._ViolinPlotter(**kws)
  1032. _, ax = plt.subplots()
  1033. p.draw_violins(ax)
  1034. nt.assert_equal(len(ax.collections), 3)
  1035. for violin, color in zip(ax.collections, palettes.color_palette()):
  1036. npt.assert_array_equal(violin.get_facecolors()[0, :-1], color)
  1037. plt.close("all")
  1038. # Test multiple violins with hue nesting
  1039. kws.update(dict(hue="h"))
  1040. p = cat._ViolinPlotter(**kws)
  1041. _, ax = plt.subplots()
  1042. p.draw_violins(ax)
  1043. nt.assert_equal(len(ax.collections), 6)
  1044. for violin, color in zip(ax.collections,
  1045. palettes.color_palette(n_colors=2) * 3):
  1046. npt.assert_array_equal(violin.get_facecolors()[0, :-1], color)
  1047. plt.close("all")
  1048. # Test multiple split violins
  1049. kws.update(dict(split=True, palette="muted"))
  1050. p = cat._ViolinPlotter(**kws)
  1051. _, ax = plt.subplots()
  1052. p.draw_violins(ax)
  1053. nt.assert_equal(len(ax.collections), 6)
  1054. for violin, color in zip(ax.collections,
  1055. palettes.color_palette("muted",
  1056. n_colors=2) * 3):
  1057. npt.assert_array_equal(violin.get_facecolors()[0, :-1], color)
  1058. plt.close("all")
  1059. def test_draw_violinplots_no_observations(self):
  1060. kws = self.default_kws.copy()
  1061. kws["inner"] = None
  1062. # Test single layer of grouping
  1063. x = ["a", "a", "b"]
  1064. y = self.rs.randn(3)
  1065. y[-1] = np.nan
  1066. kws.update(x=x, y=y)
  1067. p = cat._ViolinPlotter(**kws)
  1068. _, ax = plt.subplots()
  1069. p.draw_violins(ax)
  1070. nt.assert_equal(len(ax.collections), 1)
  1071. nt.assert_equal(len(ax.lines), 0)
  1072. plt.close("all")
  1073. # Test nested hue grouping
  1074. x = ["a"] * 4 + ["b"] * 2
  1075. y = self.rs.randn(6)
  1076. h = ["m", "n"] * 2 + ["m"] * 2
  1077. kws.update(x=x, y=y, hue=h)
  1078. p = cat._ViolinPlotter(**kws)
  1079. _, ax = plt.subplots()
  1080. p.draw_violins(ax)
  1081. nt.assert_equal(len(ax.collections), 3)
  1082. nt.assert_equal(len(ax.lines), 0)
  1083. plt.close("all")
  1084. def test_draw_violinplots_single_observations(self):
  1085. kws = self.default_kws.copy()
  1086. kws["inner"] = None
  1087. # Test single layer of grouping
  1088. x = ["a", "a", "b"]
  1089. y = self.rs.randn(3)
  1090. kws.update(x=x, y=y)
  1091. p = cat._ViolinPlotter(**kws)
  1092. _, ax = plt.subplots()
  1093. p.draw_violins(ax)
  1094. nt.assert_equal(len(ax.collections), 1)
  1095. nt.assert_equal(len(ax.lines), 1)
  1096. plt.close("all")
  1097. # Test nested hue grouping
  1098. x = ["b"] * 4 + ["a"] * 3
  1099. y = self.rs.randn(7)
  1100. h = (["m", "n"] * 4)[:-1]
  1101. kws.update(x=x, y=y, hue=h)
  1102. p = cat._ViolinPlotter(**kws)
  1103. _, ax = plt.subplots()
  1104. p.draw_violins(ax)
  1105. nt.assert_equal(len(ax.collections), 3)
  1106. nt.assert_equal(len(ax.lines), 1)
  1107. plt.close("all")
  1108. # Test nested hue grouping with split
  1109. kws["split"] = True
  1110. p = cat._ViolinPlotter(**kws)
  1111. _, ax = plt.subplots()
  1112. p.draw_violins(ax)
  1113. nt.assert_equal(len(ax.collections), 3)
  1114. nt.assert_equal(len(ax.lines), 1)
  1115. plt.close("all")
  1116. def test_violinplots(self):
  1117. # Smoke test the high level violinplot options
  1118. cat.violinplot("y", data=self.df)
  1119. plt.close("all")
  1120. cat.violinplot(y="y", data=self.df)
  1121. plt.close("all")
  1122. cat.violinplot("g", "y", data=self.df)
  1123. plt.close("all")
  1124. cat.violinplot("y", "g", data=self.df, orient="h")
  1125. plt.close("all")
  1126. cat.violinplot("g", "y", "h", data=self.df)
  1127. plt.close("all")
  1128. cat.violinplot("g", "y", "h", order=list("nabc"), data=self.df)
  1129. plt.close("all")
  1130. cat.violinplot("g", "y", "h", hue_order=list("omn"), data=self.df)
  1131. plt.close("all")
  1132. cat.violinplot("y", "g", "h", data=self.df, orient="h")
  1133. plt.close("all")
  1134. for inner in ["box", "quart", "point", "stick", None]:
  1135. cat.violinplot("g", "y", data=self.df, inner=inner)
  1136. plt.close("all")
  1137. cat.violinplot("g", "y", "h", data=self.df, inner=inner)
  1138. plt.close("all")
  1139. cat.violinplot("g", "y", "h", data=self.df,
  1140. inner=inner, split=True)
  1141. plt.close("all")
  1142. class TestCategoricalScatterPlotter(CategoricalFixture):
  1143. def test_group_point_colors(self):
  1144. p = cat._CategoricalScatterPlotter()
  1145. p.establish_variables(x="g", y="y", data=self.df)
  1146. p.establish_colors(None, "deep", 1)
  1147. point_colors = p.point_colors
  1148. n_colors = self.g.unique().size
  1149. assert len(point_colors) == n_colors
  1150. for i, group_colors in enumerate(point_colors):
  1151. for color in group_colors:
  1152. assert color == i
  1153. def test_hue_point_colors(self):
  1154. p = cat._CategoricalScatterPlotter()
  1155. hue_order = self.h.unique().tolist()
  1156. p.establish_variables(x="g", y="y", hue="h",
  1157. hue_order=hue_order, data=self.df)
  1158. p.establish_colors(None, "deep", 1)
  1159. point_colors = p.point_colors
  1160. assert len(point_colors) == self.g.unique().size
  1161. for i, group_colors in enumerate(point_colors):
  1162. group_hues = np.asarray(p.plot_hues[i])
  1163. for point_hue, point_color in zip(group_hues, group_colors):
  1164. assert point_color == p.hue_names.index(point_hue)
  1165. # hue_level = np.asarray(p.plot_hues[i])[j]
  1166. # palette_color = deep_colors[hue_order.index(hue_level)]
  1167. # assert tuple(point_color) == palette_color
  1168. def test_scatterplot_legend(self):
  1169. p = cat._CategoricalScatterPlotter()
  1170. hue_order = ["m", "n"]
  1171. p.establish_variables(x="g", y="y", hue="h",
  1172. hue_order=hue_order, data=self.df)
  1173. p.establish_colors(None, "deep", 1)
  1174. deep_colors = palettes.color_palette("deep", self.h.unique().size)
  1175. f, ax = plt.subplots()
  1176. p.add_legend_data(ax)
  1177. leg = ax.legend()
  1178. for i, t in enumerate(leg.get_texts()):
  1179. nt.assert_equal(t.get_text(), hue_order[i])
  1180. for i, h in enumerate(leg.legendHandles):
  1181. rgb = h.get_facecolor()[0, :3]
  1182. nt.assert_equal(tuple(rgb), tuple(deep_colors[i]))
  1183. class TestStripPlotter(CategoricalFixture):
  1184. def test_stripplot_vertical(self):
  1185. pal = palettes.color_palette()
  1186. ax = cat.stripplot("g", "y", jitter=False, data=self.df)
  1187. for i, (_, vals) in enumerate(self.y.groupby(self.g)):
  1188. x, y = ax.collections[i].get_offsets().T
  1189. npt.assert_array_equal(x, np.ones(len(x)) * i)
  1190. npt.assert_array_equal(y, vals)
  1191. npt.assert_equal(ax.collections[i].get_facecolors()[0, :3], pal[i])
  1192. def test_stripplot_horiztonal(self):
  1193. df = self.df.copy()
  1194. df.g = df.g.astype("category")
  1195. ax = cat.stripplot("y", "g", jitter=False, data=df)
  1196. for i, (_, vals) in enumerate(self.y.groupby(self.g)):
  1197. x, y = ax.collections[i].get_offsets().T
  1198. npt.assert_array_equal(x, vals)
  1199. npt.assert_array_equal(y, np.ones(len(x)) * i)
  1200. def test_stripplot_jitter(self):
  1201. pal = palettes.color_palette()
  1202. ax = cat.stripplot("g", "y", data=self.df, jitter=True)
  1203. for i, (_, vals) in enumerate(self.y.groupby(self.g)):
  1204. x, y = ax.collections[i].get_offsets().T
  1205. npt.assert_array_less(np.ones(len(x)) * i - .1, x)
  1206. npt.assert_array_less(x, np.ones(len(x)) * i + .1)
  1207. npt.assert_array_equal(y, vals)
  1208. npt.assert_equal(ax.collections[i].get_facecolors()[0, :3], pal[i])
  1209. def test_dodge_nested_stripplot_vertical(self):
  1210. pal = palettes.color_palette()
  1211. ax = cat.stripplot("g", "y", "h", data=self.df,
  1212. jitter=False, dodge=True)
  1213. for i, (_, group_vals) in enumerate(self.y.groupby(self.g)):
  1214. for j, (_, vals) in enumerate(group_vals.groupby(self.h)):
  1215. x, y = ax.collections[i * 2 + j].get_offsets().T
  1216. npt.assert_array_equal(x, np.ones(len(x)) * i + [-.2, .2][j])
  1217. npt.assert_array_equal(y, vals)
  1218. fc = ax.collections[i * 2 + j].get_facecolors()[0, :3]
  1219. assert tuple(fc) == pal[j]
  1220. def test_dodge_nested_stripplot_horizontal(self):
  1221. df = self.df.copy()
  1222. df.g = df.g.astype("category")
  1223. ax = cat.stripplot("y", "g", "h", data=df,
  1224. jitter=False, dodge=True)
  1225. for i, (_, group_vals) in enumerate(self.y.groupby(self.g)):
  1226. for j, (_, vals) in enumerate(group_vals.groupby(self.h)):
  1227. x, y = ax.collections[i * 2 + j].get_offsets().T
  1228. npt.assert_array_equal(x, vals)
  1229. npt.assert_array_equal(y, np.ones(len(x)) * i + [-.2, .2][j])
  1230. def test_nested_stripplot_vertical(self):
  1231. # Test a simple vertical strip plot
  1232. ax = cat.stripplot("g", "y", "h", data=self.df,
  1233. jitter=False, dodge=False)
  1234. for i, (_, group_vals) in enumerate(self.y.groupby(self.g)):
  1235. x, y = ax.collections[i].get_offsets().T
  1236. npt.assert_array_equal(x, np.ones(len(x)) * i)
  1237. npt.assert_array_equal(y, group_vals)
  1238. def test_nested_stripplot_horizontal(self):
  1239. df = self.df.copy()
  1240. df.g = df.g.astype("category")
  1241. ax = cat.stripplot("y", "g", "h", data=df,
  1242. jitter=False, dodge=False)
  1243. for i, (_, group_vals) in enumerate(self.y.groupby(self.g)):
  1244. x, y = ax.collections[i].get_offsets().T
  1245. npt.assert_array_equal(x, group_vals)
  1246. npt.assert_array_equal(y, np.ones(len(x)) * i)
  1247. def test_three_strip_points(self):
  1248. x = np.arange(3)
  1249. ax = cat.stripplot(x=x)
  1250. facecolors = ax.collections[0].get_facecolor()
  1251. nt.assert_equal(facecolors.shape, (3, 4))
  1252. npt.assert_array_equal(facecolors[0], facecolors[1])
  1253. def test_unaligned_index(self):
  1254. f, (ax1, ax2) = plt.subplots(2)
  1255. cat.stripplot(self.g, self.y, ax=ax1)
  1256. cat.stripplot(self.g, self.y_perm, ax=ax2)
  1257. for p1, p2 in zip(ax1.collections, ax2.collections):
  1258. y1, y2 = p1.get_offsets()[:, 1], p2.get_offsets()[:, 1]
  1259. assert np.array_equal(np.sort(y1), np.sort(y2))
  1260. assert np.array_equal(p1.get_facecolors()[np.argsort(y1)],
  1261. p2.get_facecolors()[np.argsort(y2)])
  1262. f, (ax1, ax2) = plt.subplots(2)
  1263. hue_order = self.h.unique()
  1264. cat.stripplot(self.g, self.y, self.h,
  1265. hue_order=hue_order, ax=ax1)
  1266. cat.stripplot(self.g, self.y_perm, self.h,
  1267. hue_order=hue_order, ax=ax2)
  1268. for p1, p2 in zip(ax1.collections, ax2.collections):
  1269. y1, y2 = p1.get_offsets()[:, 1], p2.get_offsets()[:, 1]
  1270. assert np.array_equal(np.sort(y1), np.sort(y2))
  1271. assert np.array_equal(p1.get_facecolors()[np.argsort(y1)],
  1272. p2.get_facecolors()[np.argsort(y2)])
  1273. f, (ax1, ax2) = plt.subplots(2)
  1274. hue_order = self.h.unique()
  1275. cat.stripplot(self.g, self.y, self.h,
  1276. dodge=True, hue_order=hue_order, ax=ax1)
  1277. cat.stripplot(self.g, self.y_perm, self.h,
  1278. dodge=True, hue_order=hue_order, ax=ax2)
  1279. for p1, p2 in zip(ax1.collections, ax2.collections):
  1280. y1, y2 = p1.get_offsets()[:, 1], p2.get_offsets()[:, 1]
  1281. assert np.array_equal(np.sort(y1), np.sort(y2))
  1282. assert np.array_equal(p1.get_facecolors()[np.argsort(y1)],
  1283. p2.get_facecolors()[np.argsort(y2)])
  1284. class TestSwarmPlotter(CategoricalFixture):
  1285. default_kws = dict(x=None, y=None, hue=None, data=None,
  1286. order=None, hue_order=None, dodge=False,
  1287. orient=None, color=None, palette=None)
  1288. def test_could_overlap(self):
  1289. p = cat._SwarmPlotter(**self.default_kws)
  1290. neighbors = p.could_overlap((1, 1), [(0, 0), (1, .5), (.5, .5)], 1)
  1291. npt.assert_array_equal(neighbors, [(1, .5), (.5, .5)])
  1292. def test_position_candidates(self):
  1293. p = cat._SwarmPlotter(**self.default_kws)
  1294. xy_i = (0, 1)
  1295. neighbors = [(0, 1), (0, 1.5)]
  1296. candidates = p.position_candidates(xy_i, neighbors, 1)
  1297. dx1 = 1.05
  1298. dx2 = np.sqrt(1 - .5 ** 2) * 1.05
  1299. npt.assert_array_equal(candidates,
  1300. [(0, 1), (-dx1, 1), (dx1, 1),
  1301. (dx2, 1), (-dx2, 1)])
  1302. def test_find_first_non_overlapping_candidate(self):
  1303. p = cat._SwarmPlotter(**self.default_kws)
  1304. candidates = [(.5, 1), (1, 1), (1.5, 1)]
  1305. neighbors = np.array([(0, 1)])
  1306. first = p.first_non_overlapping_candidate(candidates, neighbors, 1)
  1307. npt.assert_array_equal(first, (1, 1))
  1308. def test_beeswarm(self):
  1309. p = cat._SwarmPlotter(**self.default_kws)
  1310. d = self.y.diff().mean() * 1.5
  1311. x = np.zeros(self.y.size)
  1312. y = np.sort(self.y)
  1313. orig_xy = np.c_[x, y]
  1314. swarm = p.beeswarm(orig_xy, d)
  1315. dmat = spatial.distance.cdist(swarm, swarm)
  1316. triu = dmat[np.triu_indices_from(dmat, 1)]
  1317. npt.assert_array_less(d, triu)
  1318. npt.assert_array_equal(y, swarm[:, 1])
  1319. def test_add_gutters(self):
  1320. p = cat._SwarmPlotter(**self.default_kws)
  1321. points = np.array([0, -1, .4, .8])
  1322. points = p.add_gutters(points, 0, 1)
  1323. npt.assert_array_equal(points,
  1324. np.array([0, -.5, .4, .5]))
  1325. def test_swarmplot_vertical(self):
  1326. pal = palettes.color_palette()
  1327. ax = cat.swarmplot("g", "y", data=self.df)
  1328. for i, (_, vals) in enumerate(self.y.groupby(self.g)):
  1329. x, y = ax.collections[i].get_offsets().T
  1330. npt.assert_array_almost_equal(y, np.sort(vals))
  1331. fc = ax.collections[i].get_facecolors()[0, :3]
  1332. npt.assert_equal(fc, pal[i])
  1333. def test_swarmplot_horizontal(self):
  1334. pal = palettes.color_palette()
  1335. ax = cat.swarmplot("y", "g", data=self.df, orient="h")
  1336. for i, (_, vals) in enumerate(self.y.groupby(self.g)):
  1337. x, y = ax.collections[i].get_offsets().T
  1338. npt.assert_array_almost_equal(x, np.sort(vals))
  1339. fc = ax.collections[i].get_facecolors()[0, :3]
  1340. npt.assert_equal(fc, pal[i])
  1341. def test_dodge_nested_swarmplot_vertical(self):
  1342. pal = palettes.color_palette()
  1343. ax = cat.swarmplot("g", "y", "h", data=self.df, dodge=True)
  1344. for i, (_, group_vals) in enumerate(self.y.groupby(self.g)):
  1345. for j, (_, vals) in enumerate(group_vals.groupby(self.h)):
  1346. x, y = ax.collections[i * 2 + j].get_offsets().T
  1347. npt.assert_array_almost_equal(y, np.sort(vals))
  1348. fc = ax.collections[i * 2 + j].get_facecolors()[0, :3]
  1349. assert tuple(fc) == pal[j]
  1350. def test_dodge_nested_swarmplot_horizontal(self):
  1351. pal = palettes.color_palette()
  1352. ax = cat.swarmplot("y", "g", "h", data=self.df, orient="h", dodge=True)
  1353. for i, (_, group_vals) in enumerate(self.y.groupby(self.g)):
  1354. for j, (_, vals) in enumerate(group_vals.groupby(self.h)):
  1355. x, y = ax.collections[i * 2 + j].get_offsets().T
  1356. npt.assert_array_almost_equal(x, np.sort(vals))
  1357. fc = ax.collections[i * 2 + j].get_facecolors()[0, :3]
  1358. assert tuple(fc) == pal[j]
  1359. def test_nested_swarmplot_vertical(self):
  1360. ax = cat.swarmplot("g", "y", "h", data=self.df)
  1361. pal = palettes.color_palette()
  1362. hue_names = self.h.unique().tolist()
  1363. grouped_hues = list(self.h.groupby(self.g))
  1364. for i, (_, vals) in enumerate(self.y.groupby(self.g)):
  1365. points = ax.collections[i]
  1366. x, y = points.get_offsets().T
  1367. sorter = np.argsort(vals)
  1368. npt.assert_array_almost_equal(y, vals.iloc[sorter])
  1369. _, hue_vals = grouped_hues[i]
  1370. for hue, fc in zip(hue_vals.values[sorter.values],
  1371. points.get_facecolors()):
  1372. assert tuple(fc[:3]) == pal[hue_names.index(hue)]
  1373. def test_nested_swarmplot_horizontal(self):
  1374. ax = cat.swarmplot("y", "g", "h", data=self.df, orient="h")
  1375. pal = palettes.color_palette()
  1376. hue_names = self.h.unique().tolist()
  1377. grouped_hues = list(self.h.groupby(self.g))
  1378. for i, (_, vals) in enumerate(self.y.groupby(self.g)):
  1379. points = ax.collections[i]
  1380. x, y = points.get_offsets().T
  1381. sorter = np.argsort(vals)
  1382. npt.assert_array_almost_equal(x, vals.iloc[sorter])
  1383. _, hue_vals = grouped_hues[i]
  1384. for hue, fc in zip(hue_vals.values[sorter.values],
  1385. points.get_facecolors()):
  1386. assert tuple(fc[:3]) == pal[hue_names.index(hue)]
  1387. def test_unaligned_index(self):
  1388. f, (ax1, ax2) = plt.subplots(2)
  1389. cat.swarmplot(self.g, self.y, ax=ax1)
  1390. cat.swarmplot(self.g, self.y_perm, ax=ax2)
  1391. for p1, p2 in zip(ax1.collections, ax2.collections):
  1392. assert np.allclose(p1.get_offsets()[:, 1],
  1393. p2.get_offsets()[:, 1])
  1394. assert np.array_equal(p1.get_facecolors(),
  1395. p2.get_facecolors())
  1396. f, (ax1, ax2) = plt.subplots(2)
  1397. hue_order = self.h.unique()
  1398. cat.swarmplot(self.g, self.y, self.h,
  1399. hue_order=hue_order, ax=ax1)
  1400. cat.swarmplot(self.g, self.y_perm, self.h,
  1401. hue_order=hue_order, ax=ax2)
  1402. for p1, p2 in zip(ax1.collections, ax2.collections):
  1403. assert np.allclose(p1.get_offsets()[:, 1],
  1404. p2.get_offsets()[:, 1])
  1405. assert np.array_equal(p1.get_facecolors(),
  1406. p2.get_facecolors())
  1407. f, (ax1, ax2) = plt.subplots(2)
  1408. hue_order = self.h.unique()
  1409. cat.swarmplot(self.g, self.y, self.h,
  1410. dodge=True, hue_order=hue_order, ax=ax1)
  1411. cat.swarmplot(self.g, self.y_perm, self.h,
  1412. dodge=True, hue_order=hue_order, ax=ax2)
  1413. for p1, p2 in zip(ax1.collections, ax2.collections):
  1414. assert np.allclose(p1.get_offsets()[:, 1],
  1415. p2.get_offsets()[:, 1])
  1416. assert np.array_equal(p1.get_facecolors(),
  1417. p2.get_facecolors())
  1418. class TestBarPlotter(CategoricalFixture):
  1419. default_kws = dict(
  1420. x=None, y=None, hue=None, data=None,
  1421. estimator=np.mean, ci=95, n_boot=100, units=None, seed=None,
  1422. order=None, hue_order=None,
  1423. orient=None, color=None, palette=None,
  1424. saturation=.75, errcolor=".26", errwidth=None,
  1425. capsize=None, dodge=True
  1426. )
  1427. def test_nested_width(self):
  1428. kws = self.default_kws.copy()
  1429. p = cat._BarPlotter(**kws)
  1430. p.establish_variables("g", "y", "h", data=self.df)
  1431. nt.assert_equal(p.nested_width, .8 / 2)
  1432. p = cat._BarPlotter(**kws)
  1433. p.establish_variables("h", "y", "g", data=self.df)
  1434. nt.assert_equal(p.nested_width, .8 / 3)
  1435. kws["dodge"] = False
  1436. p = cat._BarPlotter(**kws)
  1437. p.establish_variables("h", "y", "g", data=self.df)
  1438. nt.assert_equal(p.nested_width, .8)
  1439. def test_draw_vertical_bars(self):
  1440. kws = self.default_kws.copy()
  1441. kws.update(x="g", y="y", data=self.df)
  1442. p = cat._BarPlotter(**kws)
  1443. f, ax = plt.subplots()
  1444. p.draw_bars(ax, {})
  1445. nt.assert_equal(len(ax.patches), len(p.plot_data))
  1446. nt.assert_equal(len(ax.lines), len(p.plot_data))
  1447. for bar, color in zip(ax.patches, p.colors):
  1448. nt.assert_equal(bar.get_facecolor()[:-1], color)
  1449. positions = np.arange(len(p.plot_data)) - p.width / 2
  1450. for bar, pos, stat in zip(ax.patches, positions, p.statistic):
  1451. nt.assert_equal(bar.get_x(), pos)
  1452. nt.assert_equal(bar.get_width(), p.width)
  1453. nt.assert_equal(bar.get_y(), 0)
  1454. nt.assert_equal(bar.get_height(), stat)
  1455. def test_draw_horizontal_bars(self):
  1456. kws = self.default_kws.copy()
  1457. kws.update(x="y", y="g", orient="h", data=self.df)
  1458. p = cat._BarPlotter(**kws)
  1459. f, ax = plt.subplots()
  1460. p.draw_bars(ax, {})
  1461. nt.assert_equal(len(ax.patches), len(p.plot_data))
  1462. nt.assert_equal(len(ax.lines), len(p.plot_data))
  1463. for bar, color in zip(ax.patches, p.colors):
  1464. nt.assert_equal(bar.get_facecolor()[:-1], color)
  1465. positions = np.arange(len(p.plot_data)) - p.width / 2
  1466. for bar, pos, stat in zip(ax.patches, positions, p.statistic):
  1467. nt.assert_equal(bar.get_y(), pos)
  1468. nt.assert_equal(bar.get_height(), p.width)
  1469. nt.assert_equal(bar.get_x(), 0)
  1470. nt.assert_equal(bar.get_width(), stat)
  1471. def test_draw_nested_vertical_bars(self):
  1472. kws = self.default_kws.copy()
  1473. kws.update(x="g", y="y", hue="h", data=self.df)
  1474. p = cat._BarPlotter(**kws)
  1475. f, ax = plt.subplots()
  1476. p.draw_bars(ax, {})
  1477. n_groups, n_hues = len(p.plot_data), len(p.hue_names)
  1478. nt.assert_equal(len(ax.patches), n_groups * n_hues)
  1479. nt.assert_equal(len(ax.lines), n_groups * n_hues)
  1480. for bar in ax.patches[:n_groups]:
  1481. nt.assert_equal(bar.get_facecolor()[:-1], p.colors[0])
  1482. for bar in ax.patches[n_groups:]:
  1483. nt.assert_equal(bar.get_facecolor()[:-1], p.colors[1])
  1484. positions = np.arange(len(p.plot_data))
  1485. for bar, pos in zip(ax.patches[:n_groups], positions):
  1486. nt.assert_almost_equal(bar.get_x(), pos - p.width / 2)
  1487. nt.assert_almost_equal(bar.get_width(), p.nested_width)
  1488. for bar, stat in zip(ax.patches, p.statistic.T.flat):
  1489. nt.assert_almost_equal(bar.get_y(), 0)
  1490. nt.assert_almost_equal(bar.get_height(), stat)
  1491. def test_draw_nested_horizontal_bars(self):
  1492. kws = self.default_kws.copy()
  1493. kws.update(x="y", y="g", hue="h", orient="h", data=self.df)
  1494. p = cat._BarPlotter(**kws)
  1495. f, ax = plt.subplots()
  1496. p.draw_bars(ax, {})
  1497. n_groups, n_hues = len(p.plot_data), len(p.hue_names)
  1498. nt.assert_equal(len(ax.patches), n_groups * n_hues)
  1499. nt.assert_equal(len(ax.lines), n_groups * n_hues)
  1500. for bar in ax.patches[:n_groups]:
  1501. nt.assert_equal(bar.get_facecolor()[:-1], p.colors[0])
  1502. for bar in ax.patches[n_groups:]:
  1503. nt.assert_equal(bar.get_facecolor()[:-1], p.colors[1])
  1504. positions = np.arange(len(p.plot_data))
  1505. for bar, pos in zip(ax.patches[:n_groups], positions):
  1506. nt.assert_almost_equal(bar.get_y(), pos - p.width / 2)
  1507. nt.assert_almost_equal(bar.get_height(), p.nested_width)
  1508. for bar, stat in zip(ax.patches, p.statistic.T.flat):
  1509. nt.assert_almost_equal(bar.get_x(), 0)
  1510. nt.assert_almost_equal(bar.get_width(), stat)
  1511. def test_draw_missing_bars(self):
  1512. kws = self.default_kws.copy()
  1513. order = list("abcd")
  1514. kws.update(x="g", y="y", order=order, data=self.df)
  1515. p = cat._BarPlotter(**kws)
  1516. f, ax = plt.subplots()
  1517. p.draw_bars(ax, {})
  1518. nt.assert_equal(len(ax.patches), len(order))
  1519. nt.assert_equal(len(ax.lines), len(order))
  1520. plt.close("all")
  1521. hue_order = list("mno")
  1522. kws.update(x="g", y="y", hue="h", hue_order=hue_order, data=self.df)
  1523. p = cat._BarPlotter(**kws)
  1524. f, ax = plt.subplots()
  1525. p.draw_bars(ax, {})
  1526. nt.assert_equal(len(ax.patches), len(p.plot_data) * len(hue_order))
  1527. nt.assert_equal(len(ax.lines), len(p.plot_data) * len(hue_order))
  1528. plt.close("all")
  1529. def test_unaligned_index(self):
  1530. f, (ax1, ax2) = plt.subplots(2)
  1531. cat.barplot(self.g, self.y, ci="sd", ax=ax1)
  1532. cat.barplot(self.g, self.y_perm, ci="sd", ax=ax2)
  1533. for l1, l2 in zip(ax1.lines, ax2.lines):
  1534. assert pytest.approx(l1.get_xydata()) == l2.get_xydata()
  1535. for p1, p2 in zip(ax1.patches, ax2.patches):
  1536. assert pytest.approx(p1.get_xy()) == p2.get_xy()
  1537. assert pytest.approx(p1.get_height()) == p2.get_height()
  1538. assert pytest.approx(p1.get_width()) == p2.get_width()
  1539. f, (ax1, ax2) = plt.subplots(2)
  1540. hue_order = self.h.unique()
  1541. cat.barplot(self.g, self.y, self.h, hue_order=hue_order, ci="sd",
  1542. ax=ax1)
  1543. cat.barplot(self.g, self.y_perm, self.h,
  1544. hue_order=hue_order, ci="sd", ax=ax2)
  1545. for l1, l2 in zip(ax1.lines, ax2.lines):
  1546. assert pytest.approx(l1.get_xydata()) == l2.get_xydata()
  1547. for p1, p2 in zip(ax1.patches, ax2.patches):
  1548. assert pytest.approx(p1.get_xy()) == p2.get_xy()
  1549. assert pytest.approx(p1.get_height()) == p2.get_height()
  1550. assert pytest.approx(p1.get_width()) == p2.get_width()
  1551. def test_barplot_colors(self):
  1552. # Test unnested palette colors
  1553. kws = self.default_kws.copy()
  1554. kws.update(x="g", y="y", data=self.df,
  1555. saturation=1, palette="muted")
  1556. p = cat._BarPlotter(**kws)
  1557. f, ax = plt.subplots()
  1558. p.draw_bars(ax, {})
  1559. palette = palettes.color_palette("muted", len(self.g.unique()))
  1560. for patch, pal_color in zip(ax.patches, palette):
  1561. nt.assert_equal(patch.get_facecolor()[:-1], pal_color)
  1562. plt.close("all")
  1563. # Test single color
  1564. color = (.2, .2, .3, 1)
  1565. kws = self.default_kws.copy()
  1566. kws.update(x="g", y="y", data=self.df,
  1567. saturation=1, color=color)
  1568. p = cat._BarPlotter(**kws)
  1569. f, ax = plt.subplots()
  1570. p.draw_bars(ax, {})
  1571. for patch in ax.patches:
  1572. nt.assert_equal(patch.get_facecolor(), color)
  1573. plt.close("all")
  1574. # Test nested palette colors
  1575. kws = self.default_kws.copy()
  1576. kws.update(x="g", y="y", hue="h", data=self.df,
  1577. saturation=1, palette="Set2")
  1578. p = cat._BarPlotter(**kws)
  1579. f, ax = plt.subplots()
  1580. p.draw_bars(ax, {})
  1581. palette = palettes.color_palette("Set2", len(self.h.unique()))
  1582. for patch in ax.patches[:len(self.g.unique())]:
  1583. nt.assert_equal(patch.get_facecolor()[:-1], palette[0])
  1584. for patch in ax.patches[len(self.g.unique()):]:
  1585. nt.assert_equal(patch.get_facecolor()[:-1], palette[1])
  1586. plt.close("all")
  1587. def test_simple_barplots(self):
  1588. ax = cat.barplot("g", "y", data=self.df)
  1589. nt.assert_equal(len(ax.patches), len(self.g.unique()))
  1590. nt.assert_equal(ax.get_xlabel(), "g")
  1591. nt.assert_equal(ax.get_ylabel(), "y")
  1592. plt.close("all")
  1593. ax = cat.barplot("y", "g", orient="h", data=self.df)
  1594. nt.assert_equal(len(ax.patches), len(self.g.unique()))
  1595. nt.assert_equal(ax.get_xlabel(), "y")
  1596. nt.assert_equal(ax.get_ylabel(), "g")
  1597. plt.close("all")
  1598. ax = cat.barplot("g", "y", "h", data=self.df)
  1599. nt.assert_equal(len(ax.patches),
  1600. len(self.g.unique()) * len(self.h.unique()))
  1601. nt.assert_equal(ax.get_xlabel(), "g")
  1602. nt.assert_equal(ax.get_ylabel(), "y")
  1603. plt.close("all")
  1604. ax = cat.barplot("y", "g", "h", orient="h", data=self.df)
  1605. nt.assert_equal(len(ax.patches),
  1606. len(self.g.unique()) * len(self.h.unique()))
  1607. nt.assert_equal(ax.get_xlabel(), "y")
  1608. nt.assert_equal(ax.get_ylabel(), "g")
  1609. plt.close("all")
  1610. class TestPointPlotter(CategoricalFixture):
  1611. default_kws = dict(
  1612. x=None, y=None, hue=None, data=None,
  1613. estimator=np.mean, ci=95, n_boot=100, units=None, seed=None,
  1614. order=None, hue_order=None,
  1615. markers="o", linestyles="-", dodge=0,
  1616. join=True, scale=1,
  1617. orient=None, color=None, palette=None,
  1618. )
  1619. def test_different_defualt_colors(self):
  1620. kws = self.default_kws.copy()
  1621. kws.update(dict(x="g", y="y", data=self.df))
  1622. p = cat._PointPlotter(**kws)
  1623. color = palettes.color_palette()[0]
  1624. npt.assert_array_equal(p.colors, [color, color, color])
  1625. def test_hue_offsets(self):
  1626. kws = self.default_kws.copy()
  1627. kws.update(dict(x="g", y="y", hue="h", data=self.df))
  1628. p = cat._PointPlotter(**kws)
  1629. npt.assert_array_equal(p.hue_offsets, [0, 0])
  1630. kws.update(dict(dodge=.5))
  1631. p = cat._PointPlotter(**kws)
  1632. npt.assert_array_equal(p.hue_offsets, [-.25, .25])
  1633. kws.update(dict(x="h", hue="g", dodge=0))
  1634. p = cat._PointPlotter(**kws)
  1635. npt.assert_array_equal(p.hue_offsets, [0, 0, 0])
  1636. kws.update(dict(dodge=.3))
  1637. p = cat._PointPlotter(**kws)
  1638. npt.assert_array_equal(p.hue_offsets, [-.15, 0, .15])
  1639. def test_draw_vertical_points(self):
  1640. kws = self.default_kws.copy()
  1641. kws.update(x="g", y="y", data=self.df)
  1642. p = cat._PointPlotter(**kws)
  1643. f, ax = plt.subplots()
  1644. p.draw_points(ax)
  1645. nt.assert_equal(len(ax.collections), 1)
  1646. nt.assert_equal(len(ax.lines), len(p.plot_data) + 1)
  1647. points = ax.collections[0]
  1648. nt.assert_equal(len(points.get_offsets()), len(p.plot_data))
  1649. x, y = points.get_offsets().T
  1650. npt.assert_array_equal(x, np.arange(len(p.plot_data)))
  1651. npt.assert_array_equal(y, p.statistic)
  1652. for got_color, want_color in zip(points.get_facecolors(),
  1653. p.colors):
  1654. npt.assert_array_equal(got_color[:-1], want_color)
  1655. def test_draw_horizontal_points(self):
  1656. kws = self.default_kws.copy()
  1657. kws.update(x="y", y="g", orient="h", data=self.df)
  1658. p = cat._PointPlotter(**kws)
  1659. f, ax = plt.subplots()
  1660. p.draw_points(ax)
  1661. nt.assert_equal(len(ax.collections), 1)
  1662. nt.assert_equal(len(ax.lines), len(p.plot_data) + 1)
  1663. points = ax.collections[0]
  1664. nt.assert_equal(len(points.get_offsets()), len(p.plot_data))
  1665. x, y = points.get_offsets().T
  1666. npt.assert_array_equal(x, p.statistic)
  1667. npt.assert_array_equal(y, np.arange(len(p.plot_data)))
  1668. for got_color, want_color in zip(points.get_facecolors(),
  1669. p.colors):
  1670. npt.assert_array_equal(got_color[:-1], want_color)
  1671. def test_draw_vertical_nested_points(self):
  1672. kws = self.default_kws.copy()
  1673. kws.update(x="g", y="y", hue="h", data=self.df)
  1674. p = cat._PointPlotter(**kws)
  1675. f, ax = plt.subplots()
  1676. p.draw_points(ax)
  1677. nt.assert_equal(len(ax.collections), 2)
  1678. nt.assert_equal(len(ax.lines),
  1679. len(p.plot_data) * len(p.hue_names) + len(p.hue_names))
  1680. for points, numbers, color in zip(ax.collections,
  1681. p.statistic.T,
  1682. p.colors):
  1683. nt.assert_equal(len(points.get_offsets()), len(p.plot_data))
  1684. x, y = points.get_offsets().T
  1685. npt.assert_array_equal(x, np.arange(len(p.plot_data)))
  1686. npt.assert_array_equal(y, numbers)
  1687. for got_color in points.get_facecolors():
  1688. npt.assert_array_equal(got_color[:-1], color)
  1689. def test_draw_horizontal_nested_points(self):
  1690. kws = self.default_kws.copy()
  1691. kws.update(x="y", y="g", hue="h", orient="h", data=self.df)
  1692. p = cat._PointPlotter(**kws)
  1693. f, ax = plt.subplots()
  1694. p.draw_points(ax)
  1695. nt.assert_equal(len(ax.collections), 2)
  1696. nt.assert_equal(len(ax.lines),
  1697. len(p.plot_data) * len(p.hue_names) + len(p.hue_names))
  1698. for points, numbers, color in zip(ax.collections,
  1699. p.statistic.T,
  1700. p.colors):
  1701. nt.assert_equal(len(points.get_offsets()), len(p.plot_data))
  1702. x, y = points.get_offsets().T
  1703. npt.assert_array_equal(x, numbers)
  1704. npt.assert_array_equal(y, np.arange(len(p.plot_data)))
  1705. for got_color in points.get_facecolors():
  1706. npt.assert_array_equal(got_color[:-1], color)
  1707. def test_draw_missing_points(self):
  1708. kws = self.default_kws.copy()
  1709. df = self.df.copy()
  1710. kws.update(x="g", y="y", hue="h", hue_order=["x", "y"], data=df)
  1711. p = cat._PointPlotter(**kws)
  1712. f, ax = plt.subplots()
  1713. p.draw_points(ax)
  1714. df.loc[df["h"] == "m", "y"] = np.nan
  1715. kws.update(x="g", y="y", hue="h", data=df)
  1716. p = cat._PointPlotter(**kws)
  1717. f, ax = plt.subplots()
  1718. p.draw_points(ax)
  1719. def test_unaligned_index(self):
  1720. f, (ax1, ax2) = plt.subplots(2)
  1721. cat.pointplot(self.g, self.y, ci="sd", ax=ax1)
  1722. cat.pointplot(self.g, self.y_perm, ci="sd", ax=ax2)
  1723. for l1, l2 in zip(ax1.lines, ax2.lines):
  1724. assert pytest.approx(l1.get_xydata()) == l2.get_xydata()
  1725. for p1, p2 in zip(ax1.collections, ax2.collections):
  1726. assert pytest.approx(p1.get_offsets()) == p2.get_offsets()
  1727. f, (ax1, ax2) = plt.subplots(2)
  1728. hue_order = self.h.unique()
  1729. cat.pointplot(self.g, self.y, self.h,
  1730. hue_order=hue_order, ci="sd", ax=ax1)
  1731. cat.pointplot(self.g, self.y_perm, self.h,
  1732. hue_order=hue_order, ci="sd", ax=ax2)
  1733. for l1, l2 in zip(ax1.lines, ax2.lines):
  1734. assert pytest.approx(l1.get_xydata()) == l2.get_xydata()
  1735. for p1, p2 in zip(ax1.collections, ax2.collections):
  1736. assert pytest.approx(p1.get_offsets()) == p2.get_offsets()
  1737. def test_pointplot_colors(self):
  1738. # Test a single-color unnested plot
  1739. color = (.2, .2, .3, 1)
  1740. kws = self.default_kws.copy()
  1741. kws.update(x="g", y="y", data=self.df, color=color)
  1742. p = cat._PointPlotter(**kws)
  1743. f, ax = plt.subplots()
  1744. p.draw_points(ax)
  1745. for line in ax.lines:
  1746. nt.assert_equal(line.get_color(), color[:-1])
  1747. for got_color in ax.collections[0].get_facecolors():
  1748. npt.assert_array_equal(rgb2hex(got_color), rgb2hex(color))
  1749. plt.close("all")
  1750. # Test a multi-color unnested plot
  1751. palette = palettes.color_palette("Set1", 3)
  1752. kws.update(x="g", y="y", data=self.df, palette="Set1")
  1753. p = cat._PointPlotter(**kws)
  1754. nt.assert_true(not p.join)
  1755. f, ax = plt.subplots()
  1756. p.draw_points(ax)
  1757. for line, pal_color in zip(ax.lines, palette):
  1758. npt.assert_array_equal(line.get_color(), pal_color)
  1759. for point_color, pal_color in zip(ax.collections[0].get_facecolors(),
  1760. palette):
  1761. npt.assert_array_equal(rgb2hex(point_color), rgb2hex(pal_color))
  1762. plt.close("all")
  1763. # Test a multi-colored nested plot
  1764. palette = palettes.color_palette("dark", 2)
  1765. kws.update(x="g", y="y", hue="h", data=self.df, palette="dark")
  1766. p = cat._PointPlotter(**kws)
  1767. f, ax = plt.subplots()
  1768. p.draw_points(ax)
  1769. for line in ax.lines[:(len(p.plot_data) + 1)]:
  1770. nt.assert_equal(line.get_color(), palette[0])
  1771. for line in ax.lines[(len(p.plot_data) + 1):]:
  1772. nt.assert_equal(line.get_color(), palette[1])
  1773. for i, pal_color in enumerate(palette):
  1774. for point_color in ax.collections[i].get_facecolors():
  1775. npt.assert_array_equal(point_color[:-1], pal_color)
  1776. plt.close("all")
  1777. def test_simple_pointplots(self):
  1778. ax = cat.pointplot("g", "y", data=self.df)
  1779. nt.assert_equal(len(ax.collections), 1)
  1780. nt.assert_equal(len(ax.lines), len(self.g.unique()) + 1)
  1781. nt.assert_equal(ax.get_xlabel(), "g")
  1782. nt.assert_equal(ax.get_ylabel(), "y")
  1783. plt.close("all")
  1784. ax = cat.pointplot("y", "g", orient="h", data=self.df)
  1785. nt.assert_equal(len(ax.collections), 1)
  1786. nt.assert_equal(len(ax.lines), len(self.g.unique()) + 1)
  1787. nt.assert_equal(ax.get_xlabel(), "y")
  1788. nt.assert_equal(ax.get_ylabel(), "g")
  1789. plt.close("all")
  1790. ax = cat.pointplot("g", "y", "h", data=self.df)
  1791. nt.assert_equal(len(ax.collections), len(self.h.unique()))
  1792. nt.assert_equal(len(ax.lines),
  1793. (len(self.g.unique()) *
  1794. len(self.h.unique()) +
  1795. len(self.h.unique())))
  1796. nt.assert_equal(ax.get_xlabel(), "g")
  1797. nt.assert_equal(ax.get_ylabel(), "y")
  1798. plt.close("all")
  1799. ax = cat.pointplot("y", "g", "h", orient="h", data=self.df)
  1800. nt.assert_equal(len(ax.collections), len(self.h.unique()))
  1801. nt.assert_equal(len(ax.lines),
  1802. (len(self.g.unique()) *
  1803. len(self.h.unique()) +
  1804. len(self.h.unique())))
  1805. nt.assert_equal(ax.get_xlabel(), "y")
  1806. nt.assert_equal(ax.get_ylabel(), "g")
  1807. plt.close("all")
  1808. class TestCountPlot(CategoricalFixture):
  1809. def test_plot_elements(self):
  1810. ax = cat.countplot("g", data=self.df)
  1811. nt.assert_equal(len(ax.patches), self.g.unique().size)
  1812. for p in ax.patches:
  1813. nt.assert_equal(p.get_y(), 0)
  1814. nt.assert_equal(p.get_height(),
  1815. self.g.size / self.g.unique().size)
  1816. plt.close("all")
  1817. ax = cat.countplot(y="g", data=self.df)
  1818. nt.assert_equal(len(ax.patches), self.g.unique().size)
  1819. for p in ax.patches:
  1820. nt.assert_equal(p.get_x(), 0)
  1821. nt.assert_equal(p.get_width(),
  1822. self.g.size / self.g.unique().size)
  1823. plt.close("all")
  1824. ax = cat.countplot("g", hue="h", data=self.df)
  1825. nt.assert_equal(len(ax.patches),
  1826. self.g.unique().size * self.h.unique().size)
  1827. plt.close("all")
  1828. ax = cat.countplot(y="g", hue="h", data=self.df)
  1829. nt.assert_equal(len(ax.patches),
  1830. self.g.unique().size * self.h.unique().size)
  1831. plt.close("all")
  1832. def test_input_error(self):
  1833. with nt.assert_raises(TypeError):
  1834. cat.countplot()
  1835. with nt.assert_raises(TypeError):
  1836. cat.countplot(x="g", y="h", data=self.df)
  1837. class TestCatPlot(CategoricalFixture):
  1838. def test_facet_organization(self):
  1839. g = cat.catplot("g", "y", data=self.df)
  1840. nt.assert_equal(g.axes.shape, (1, 1))
  1841. g = cat.catplot("g", "y", col="h", data=self.df)
  1842. nt.assert_equal(g.axes.shape, (1, 2))
  1843. g = cat.catplot("g", "y", row="h", data=self.df)
  1844. nt.assert_equal(g.axes.shape, (2, 1))
  1845. g = cat.catplot("g", "y", col="u", row="h", data=self.df)
  1846. nt.assert_equal(g.axes.shape, (2, 3))
  1847. def test_plot_elements(self):
  1848. g = cat.catplot("g", "y", data=self.df, kind="point")
  1849. nt.assert_equal(len(g.ax.collections), 1)
  1850. want_lines = self.g.unique().size + 1
  1851. nt.assert_equal(len(g.ax.lines), want_lines)
  1852. g = cat.catplot("g", "y", "h", data=self.df, kind="point")
  1853. want_collections = self.h.unique().size
  1854. nt.assert_equal(len(g.ax.collections), want_collections)
  1855. want_lines = (self.g.unique().size + 1) * self.h.unique().size
  1856. nt.assert_equal(len(g.ax.lines), want_lines)
  1857. g = cat.catplot("g", "y", data=self.df, kind="bar")
  1858. want_elements = self.g.unique().size
  1859. nt.assert_equal(len(g.ax.patches), want_elements)
  1860. nt.assert_equal(len(g.ax.lines), want_elements)
  1861. g = cat.catplot("g", "y", "h", data=self.df, kind="bar")
  1862. want_elements = self.g.unique().size * self.h.unique().size
  1863. nt.assert_equal(len(g.ax.patches), want_elements)
  1864. nt.assert_equal(len(g.ax.lines), want_elements)
  1865. g = cat.catplot("g", data=self.df, kind="count")
  1866. want_elements = self.g.unique().size
  1867. nt.assert_equal(len(g.ax.patches), want_elements)
  1868. nt.assert_equal(len(g.ax.lines), 0)
  1869. g = cat.catplot("g", hue="h", data=self.df, kind="count")
  1870. want_elements = self.g.unique().size * self.h.unique().size
  1871. nt.assert_equal(len(g.ax.patches), want_elements)
  1872. nt.assert_equal(len(g.ax.lines), 0)
  1873. g = cat.catplot("g", "y", data=self.df, kind="box")
  1874. want_artists = self.g.unique().size
  1875. nt.assert_equal(len(g.ax.artists), want_artists)
  1876. g = cat.catplot("g", "y", "h", data=self.df, kind="box")
  1877. want_artists = self.g.unique().size * self.h.unique().size
  1878. nt.assert_equal(len(g.ax.artists), want_artists)
  1879. g = cat.catplot("g", "y", data=self.df,
  1880. kind="violin", inner=None)
  1881. want_elements = self.g.unique().size
  1882. nt.assert_equal(len(g.ax.collections), want_elements)
  1883. g = cat.catplot("g", "y", "h", data=self.df,
  1884. kind="violin", inner=None)
  1885. want_elements = self.g.unique().size * self.h.unique().size
  1886. nt.assert_equal(len(g.ax.collections), want_elements)
  1887. g = cat.catplot("g", "y", data=self.df, kind="strip")
  1888. want_elements = self.g.unique().size
  1889. nt.assert_equal(len(g.ax.collections), want_elements)
  1890. g = cat.catplot("g", "y", "h", data=self.df, kind="strip")
  1891. want_elements = self.g.unique().size + self.h.unique().size
  1892. nt.assert_equal(len(g.ax.collections), want_elements)
  1893. def test_bad_plot_kind_error(self):
  1894. with nt.assert_raises(ValueError):
  1895. cat.catplot("g", "y", data=self.df, kind="not_a_kind")
  1896. def test_count_x_and_y(self):
  1897. with nt.assert_raises(ValueError):
  1898. cat.catplot("g", "y", data=self.df, kind="count")
  1899. def test_plot_colors(self):
  1900. ax = cat.barplot("g", "y", data=self.df)
  1901. g = cat.catplot("g", "y", data=self.df, kind="bar")
  1902. for p1, p2 in zip(ax.patches, g.ax.patches):
  1903. nt.assert_equal(p1.get_facecolor(), p2.get_facecolor())
  1904. plt.close("all")
  1905. ax = cat.barplot("g", "y", data=self.df, color="purple")
  1906. g = cat.catplot("g", "y", data=self.df,
  1907. kind="bar", color="purple")
  1908. for p1, p2 in zip(ax.patches, g.ax.patches):
  1909. nt.assert_equal(p1.get_facecolor(), p2.get_facecolor())
  1910. plt.close("all")
  1911. ax = cat.barplot("g", "y", data=self.df, palette="Set2")
  1912. g = cat.catplot("g", "y", data=self.df,
  1913. kind="bar", palette="Set2")
  1914. for p1, p2 in zip(ax.patches, g.ax.patches):
  1915. nt.assert_equal(p1.get_facecolor(), p2.get_facecolor())
  1916. plt.close("all")
  1917. ax = cat.pointplot("g", "y", data=self.df)
  1918. g = cat.catplot("g", "y", data=self.df)
  1919. for l1, l2 in zip(ax.lines, g.ax.lines):
  1920. nt.assert_equal(l1.get_color(), l2.get_color())
  1921. plt.close("all")
  1922. ax = cat.pointplot("g", "y", data=self.df, color="purple")
  1923. g = cat.catplot("g", "y", data=self.df, color="purple")
  1924. for l1, l2 in zip(ax.lines, g.ax.lines):
  1925. nt.assert_equal(l1.get_color(), l2.get_color())
  1926. plt.close("all")
  1927. ax = cat.pointplot("g", "y", data=self.df, palette="Set2")
  1928. g = cat.catplot("g", "y", data=self.df, palette="Set2")
  1929. for l1, l2 in zip(ax.lines, g.ax.lines):
  1930. nt.assert_equal(l1.get_color(), l2.get_color())
  1931. plt.close("all")
  1932. def test_ax_kwarg_removal(self):
  1933. f, ax = plt.subplots()
  1934. with pytest.warns(UserWarning):
  1935. g = cat.catplot("g", "y", data=self.df, ax=ax)
  1936. assert len(ax.collections) == 0
  1937. assert len(g.ax.collections) > 0
  1938. def test_factorplot(self):
  1939. with pytest.warns(UserWarning):
  1940. g = cat.factorplot("g", "y", data=self.df)
  1941. nt.assert_equal(len(g.ax.collections), 1)
  1942. want_lines = self.g.unique().size + 1
  1943. nt.assert_equal(len(g.ax.lines), want_lines)
  1944. class TestBoxenPlotter(CategoricalFixture):
  1945. default_kws = dict(x=None, y=None, hue=None, data=None,
  1946. order=None, hue_order=None,
  1947. orient=None, color=None, palette=None,
  1948. saturation=.75, width=.8, dodge=True,
  1949. k_depth='proportion', linewidth=None,
  1950. scale='exponential', outlier_prop=None,
  1951. showfliers=True)
  1952. def ispatch(self, c):
  1953. return isinstance(c, mpl.collections.PatchCollection)
  1954. def ispath(self, c):
  1955. return isinstance(c, mpl.collections.PathCollection)
  1956. def edge_calc(self, n, data):
  1957. q = np.asanyarray([0.5 ** n, 1 - 0.5 ** n]) * 100
  1958. q = list(np.unique(q))
  1959. return np.percentile(data, q)
  1960. def test_box_ends_finite(self):
  1961. p = cat._LVPlotter(**self.default_kws)
  1962. p.establish_variables("g", "y", data=self.df)
  1963. box_k = np.asarray([[b, k]
  1964. for b, k in map(p._lv_box_ends, p.plot_data)])
  1965. box_ends = box_k[:, 0]
  1966. k_vals = box_k[:, 1]
  1967. # Check that all the box ends are finite and are within
  1968. # the bounds of the data
  1969. b_e = map(lambda a: np.all(np.isfinite(a)), box_ends)
  1970. assert np.sum(list(b_e)) == len(box_ends)
  1971. def within(t):
  1972. a, d = t
  1973. return ((np.ravel(a) <= d.max()) &
  1974. (np.ravel(a) >= d.min())).all()
  1975. b_w = map(within, zip(box_ends, p.plot_data))
  1976. assert np.sum(list(b_w)) == len(box_ends)
  1977. k_f = map(lambda k: (k > 0.) & np.isfinite(k), k_vals)
  1978. assert np.sum(list(k_f)) == len(k_vals)
  1979. def test_box_ends_correct(self):
  1980. n = 100
  1981. linear_data = np.arange(n)
  1982. expected_k = int(np.log2(n)) - int(np.log2(n * 0.007)) + 1
  1983. expected_edges = [self.edge_calc(i, linear_data)
  1984. for i in range(expected_k + 2, 1, -1)]
  1985. p = cat._LVPlotter(**self.default_kws)
  1986. calc_edges, calc_k = p._lv_box_ends(linear_data)
  1987. assert np.array_equal(expected_edges, calc_edges)
  1988. assert expected_k == calc_k
  1989. def test_outliers(self):
  1990. n = 100
  1991. outlier_data = np.append(np.arange(n - 1), 2 * n)
  1992. expected_k = int(np.log2(n)) - int(np.log2(n * 0.007)) + 1
  1993. expected_edges = [self.edge_calc(i, outlier_data)
  1994. for i in range(expected_k + 2, 1, -1)]
  1995. p = cat._LVPlotter(**self.default_kws)
  1996. calc_edges, calc_k = p._lv_box_ends(outlier_data)
  1997. npt.assert_equal(list(expected_edges), calc_edges)
  1998. npt.assert_equal(expected_k, calc_k)
  1999. out_calc = p._lv_outliers(outlier_data, calc_k)
  2000. out_exp = p._lv_outliers(outlier_data, expected_k)
  2001. npt.assert_equal(out_exp, out_calc)
  2002. def test_showfliers(self):
  2003. ax = cat.boxenplot("g", "y", data=self.df)
  2004. for c in filter(self.ispath, ax.collections):
  2005. assert len(c.get_offsets()) == 2
  2006. plt.close("all")
  2007. ax = cat.boxenplot("g", "y", data=self.df, showfliers=False)
  2008. for c in filter(self.ispath, ax.collections):
  2009. assert len(c.get_offsets()) == 0
  2010. plt.close("all")
  2011. def test_hue_offsets(self):
  2012. p = cat._LVPlotter(**self.default_kws)
  2013. p.establish_variables("g", "y", "h", data=self.df)
  2014. npt.assert_array_equal(p.hue_offsets, [-.2, .2])
  2015. kws = self.default_kws.copy()
  2016. kws["width"] = .6
  2017. p = cat._LVPlotter(**kws)
  2018. p.establish_variables("g", "y", "h", data=self.df)
  2019. npt.assert_array_equal(p.hue_offsets, [-.15, .15])
  2020. p = cat._LVPlotter(**kws)
  2021. p.establish_variables("h", "y", "g", data=self.df)
  2022. npt.assert_array_almost_equal(p.hue_offsets, [-.2, 0, .2])
  2023. def test_axes_data(self):
  2024. ax = cat.boxenplot("g", "y", data=self.df)
  2025. patches = filter(self.ispatch, ax.collections)
  2026. nt.assert_equal(len(list(patches)), 3)
  2027. plt.close("all")
  2028. ax = cat.boxenplot("g", "y", "h", data=self.df)
  2029. patches = filter(self.ispatch, ax.collections)
  2030. nt.assert_equal(len(list(patches)), 6)
  2031. plt.close("all")
  2032. def test_box_colors(self):
  2033. ax = cat.boxenplot("g", "y", data=self.df, saturation=1)
  2034. pal = palettes.color_palette(n_colors=3)
  2035. for patch, color in zip(ax.artists, pal):
  2036. nt.assert_equal(patch.get_facecolor()[:3], color)
  2037. plt.close("all")
  2038. ax = cat.boxenplot("g", "y", "h", data=self.df, saturation=1)
  2039. pal = palettes.color_palette(n_colors=2)
  2040. for patch, color in zip(ax.artists, pal * 2):
  2041. nt.assert_equal(patch.get_facecolor()[:3], color)
  2042. plt.close("all")
  2043. def test_draw_missing_boxes(self):
  2044. ax = cat.boxenplot("g", "y", data=self.df,
  2045. order=["a", "b", "c", "d"])
  2046. patches = filter(self.ispatch, ax.collections)
  2047. nt.assert_equal(len(list(patches)), 3)
  2048. plt.close("all")
  2049. def test_unaligned_index(self):
  2050. f, (ax1, ax2) = plt.subplots(2)
  2051. cat.boxenplot(self.g, self.y, ax=ax1)
  2052. cat.boxenplot(self.g, self.y_perm, ax=ax2)
  2053. for l1, l2 in zip(ax1.lines, ax2.lines):
  2054. assert np.array_equal(l1.get_xydata(), l2.get_xydata())
  2055. f, (ax1, ax2) = plt.subplots(2)
  2056. hue_order = self.h.unique()
  2057. cat.boxenplot(self.g, self.y, self.h, hue_order=hue_order, ax=ax1)
  2058. cat.boxenplot(self.g, self.y_perm, self.h,
  2059. hue_order=hue_order, ax=ax2)
  2060. for l1, l2 in zip(ax1.lines, ax2.lines):
  2061. assert np.array_equal(l1.get_xydata(), l2.get_xydata())
  2062. def test_missing_data(self):
  2063. x = ["a", "a", "b", "b", "c", "c", "d", "d"]
  2064. h = ["x", "y", "x", "y", "x", "y", "x", "y"]
  2065. y = self.rs.randn(8)
  2066. y[-2:] = np.nan
  2067. ax = cat.boxenplot(x, y)
  2068. nt.assert_equal(len(ax.lines), 3)
  2069. plt.close("all")
  2070. y[-1] = 0
  2071. ax = cat.boxenplot(x, y, h)
  2072. nt.assert_equal(len(ax.lines), 7)
  2073. plt.close("all")
  2074. def test_boxenplots(self):
  2075. # Smoke test the high level boxenplot options
  2076. cat.boxenplot("y", data=self.df)
  2077. plt.close("all")
  2078. cat.boxenplot(y="y", data=self.df)
  2079. plt.close("all")
  2080. cat.boxenplot("g", "y", data=self.df)
  2081. plt.close("all")
  2082. cat.boxenplot("y", "g", data=self.df, orient="h")
  2083. plt.close("all")
  2084. cat.boxenplot("g", "y", "h", data=self.df)
  2085. plt.close("all")
  2086. cat.boxenplot("g", "y", "h", order=list("nabc"), data=self.df)
  2087. plt.close("all")
  2088. cat.boxenplot("g", "y", "h", hue_order=list("omn"), data=self.df)
  2089. plt.close("all")
  2090. cat.boxenplot("y", "g", "h", data=self.df, orient="h")
  2091. plt.close("all")
  2092. cat.boxenplot("y", "g", "h", data=self.df, orient="h", palette="Set2")
  2093. plt.close("all")
  2094. cat.boxenplot("y", "g", "h", data=self.df, orient="h", color="b")
  2095. plt.close("all")
  2096. def test_axes_annotation(self):
  2097. ax = cat.boxenplot("g", "y", data=self.df)
  2098. nt.assert_equal(ax.get_xlabel(), "g")
  2099. nt.assert_equal(ax.get_ylabel(), "y")
  2100. nt.assert_equal(ax.get_xlim(), (-.5, 2.5))
  2101. npt.assert_array_equal(ax.get_xticks(), [0, 1, 2])
  2102. npt.assert_array_equal([l.get_text() for l in ax.get_xticklabels()],
  2103. ["a", "b", "c"])
  2104. plt.close("all")
  2105. ax = cat.boxenplot("g", "y", "h", data=self.df)
  2106. nt.assert_equal(ax.get_xlabel(), "g")
  2107. nt.assert_equal(ax.get_ylabel(), "y")
  2108. npt.assert_array_equal(ax.get_xticks(), [0, 1, 2])
  2109. npt.assert_array_equal([l.get_text() for l in ax.get_xticklabels()],
  2110. ["a", "b", "c"])
  2111. npt.assert_array_equal([l.get_text() for l in ax.legend_.get_texts()],
  2112. ["m", "n"])
  2113. plt.close("all")
  2114. ax = cat.boxenplot("y", "g", data=self.df, orient="h")
  2115. nt.assert_equal(ax.get_xlabel(), "y")
  2116. nt.assert_equal(ax.get_ylabel(), "g")
  2117. nt.assert_equal(ax.get_ylim(), (2.5, -.5))
  2118. npt.assert_array_equal(ax.get_yticks(), [0, 1, 2])
  2119. npt.assert_array_equal([l.get_text() for l in ax.get_yticklabels()],
  2120. ["a", "b", "c"])
  2121. plt.close("all")
  2122. @pytest.mark.parametrize("size", ["large", "medium", "small", 22, 12])
  2123. def test_legend_titlesize(self, size):
  2124. if LooseVersion(mpl.__version__) >= LooseVersion("3.0"):
  2125. rc_ctx = {"legend.title_fontsize": size}
  2126. else: # Old matplotlib doesn't have legend.title_fontsize rcparam
  2127. rc_ctx = {"axes.labelsize": size}
  2128. if isinstance(size, int):
  2129. size = size * .85
  2130. exp = mpl.font_manager.FontProperties(size=size).get_size()
  2131. with plt.rc_context(rc=rc_ctx):
  2132. ax = cat.boxenplot("g", "y", "h", data=self.df)
  2133. obs = ax.get_legend().get_title().get_fontproperties().get_size()
  2134. assert obs == exp
  2135. plt.close("all")
  2136. def test_lvplot(self):
  2137. with pytest.warns(UserWarning):
  2138. ax = cat.lvplot("g", "y", data=self.df)
  2139. patches = filter(self.ispatch, ax.collections)
  2140. nt.assert_equal(len(list(patches)), 3)
  2141. plt.close("all")