hierarchy.py 145 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180
  1. """
  2. Hierarchical clustering (:mod:`scipy.cluster.hierarchy`)
  3. ========================================================
  4. .. currentmodule:: scipy.cluster.hierarchy
  5. These functions cut hierarchical clusterings into flat clusterings
  6. or find the roots of the forest formed by a cut by providing the flat
  7. cluster ids of each observation.
  8. .. autosummary::
  9. :toctree: generated/
  10. fcluster
  11. fclusterdata
  12. leaders
  13. These are routines for agglomerative clustering.
  14. .. autosummary::
  15. :toctree: generated/
  16. linkage
  17. single
  18. complete
  19. average
  20. weighted
  21. centroid
  22. median
  23. ward
  24. These routines compute statistics on hierarchies.
  25. .. autosummary::
  26. :toctree: generated/
  27. cophenet
  28. from_mlab_linkage
  29. inconsistent
  30. maxinconsts
  31. maxdists
  32. maxRstat
  33. to_mlab_linkage
  34. Routines for visualizing flat clusters.
  35. .. autosummary::
  36. :toctree: generated/
  37. dendrogram
  38. These are data structures and routines for representing hierarchies as
  39. tree objects.
  40. .. autosummary::
  41. :toctree: generated/
  42. ClusterNode
  43. leaves_list
  44. to_tree
  45. cut_tree
  46. optimal_leaf_ordering
  47. These are predicates for checking the validity of linkage and
  48. inconsistency matrices as well as for checking isomorphism of two
  49. flat cluster assignments.
  50. .. autosummary::
  51. :toctree: generated/
  52. is_valid_im
  53. is_valid_linkage
  54. is_isomorphic
  55. is_monotonic
  56. correspond
  57. num_obs_linkage
  58. Utility routines for plotting:
  59. .. autosummary::
  60. :toctree: generated/
  61. set_link_color_palette
  62. Utility classes:
  63. .. autosummary::
  64. :toctree: generated/
  65. DisjointSet -- data structure for incremental connectivity queries
  66. """
  67. # Copyright (C) Damian Eads, 2007-2008. New BSD License.
  68. # hierarchy.py (derived from cluster.py, http://scipy-cluster.googlecode.com)
  69. #
  70. # Author: Damian Eads
  71. # Date: September 22, 2007
  72. #
  73. # Copyright (c) 2007, 2008, Damian Eads
  74. #
  75. # All rights reserved.
  76. #
  77. # Redistribution and use in source and binary forms, with or without
  78. # modification, are permitted provided that the following conditions
  79. # are met:
  80. # - Redistributions of source code must retain the above
  81. # copyright notice, this list of conditions and the
  82. # following disclaimer.
  83. # - Redistributions in binary form must reproduce the above copyright
  84. # notice, this list of conditions and the following disclaimer
  85. # in the documentation and/or other materials provided with the
  86. # distribution.
  87. # - Neither the name of the author nor the names of its
  88. # contributors may be used to endorse or promote products derived
  89. # from this software without specific prior written permission.
  90. #
  91. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  92. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  93. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  94. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  95. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  96. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  97. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  98. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  99. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  100. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  101. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  102. import warnings
  103. import bisect
  104. from collections import deque
  105. import numpy as np
  106. from . import _hierarchy, _optimal_leaf_ordering
  107. import scipy.spatial.distance as distance
  108. from scipy._lib._disjoint_set import DisjointSet
  109. _LINKAGE_METHODS = {'single': 0, 'complete': 1, 'average': 2, 'centroid': 3,
  110. 'median': 4, 'ward': 5, 'weighted': 6}
  111. _EUCLIDEAN_METHODS = ('centroid', 'median', 'ward')
  112. __all__ = ['ClusterNode', 'DisjointSet', 'average', 'centroid', 'complete',
  113. 'cophenet', 'correspond', 'cut_tree', 'dendrogram', 'fcluster',
  114. 'fclusterdata', 'from_mlab_linkage', 'inconsistent',
  115. 'is_isomorphic', 'is_monotonic', 'is_valid_im', 'is_valid_linkage',
  116. 'leaders', 'leaves_list', 'linkage', 'maxRstat', 'maxdists',
  117. 'maxinconsts', 'median', 'num_obs_linkage', 'optimal_leaf_ordering',
  118. 'set_link_color_palette', 'single', 'to_mlab_linkage', 'to_tree',
  119. 'ward', 'weighted']
  120. class ClusterWarning(UserWarning):
  121. pass
  122. def _warning(s):
  123. warnings.warn('scipy.cluster: %s' % s, ClusterWarning, stacklevel=3)
  124. def _copy_array_if_base_present(a):
  125. """
  126. Copy the array if its base points to a parent array.
  127. """
  128. if a.base is not None:
  129. return a.copy()
  130. elif np.issubsctype(a, np.float32):
  131. return np.array(a, dtype=np.double)
  132. else:
  133. return a
  134. def _copy_arrays_if_base_present(T):
  135. """
  136. Accept a tuple of arrays T. Copies the array T[i] if its base array
  137. points to an actual array. Otherwise, the reference is just copied.
  138. This is useful if the arrays are being passed to a C function that
  139. does not do proper striding.
  140. """
  141. l = [_copy_array_if_base_present(a) for a in T]
  142. return l
  143. def _randdm(pnts):
  144. """
  145. Generate a random distance matrix stored in condensed form.
  146. Parameters
  147. ----------
  148. pnts : int
  149. The number of points in the distance matrix. Has to be at least 2.
  150. Returns
  151. -------
  152. D : ndarray
  153. A ``pnts * (pnts - 1) / 2`` sized vector is returned.
  154. """
  155. if pnts >= 2:
  156. D = np.random.rand(pnts * (pnts - 1) / 2)
  157. else:
  158. raise ValueError("The number of points in the distance matrix "
  159. "must be at least 2.")
  160. return D
  161. def single(y):
  162. """
  163. Perform single/min/nearest linkage on the condensed distance matrix ``y``.
  164. Parameters
  165. ----------
  166. y : ndarray
  167. The upper triangular of the distance matrix. The result of
  168. ``pdist`` is returned in this form.
  169. Returns
  170. -------
  171. Z : ndarray
  172. The linkage matrix.
  173. See Also
  174. --------
  175. linkage : for advanced creation of hierarchical clusterings.
  176. scipy.spatial.distance.pdist : pairwise distance metrics
  177. Examples
  178. --------
  179. >>> from scipy.cluster.hierarchy import single, fcluster
  180. >>> from scipy.spatial.distance import pdist
  181. First, we need a toy dataset to play with::
  182. x x x x
  183. x x
  184. x x
  185. x x x x
  186. >>> X = [[0, 0], [0, 1], [1, 0],
  187. ... [0, 4], [0, 3], [1, 4],
  188. ... [4, 0], [3, 0], [4, 1],
  189. ... [4, 4], [3, 4], [4, 3]]
  190. Then, we get a condensed distance matrix from this dataset:
  191. >>> y = pdist(X)
  192. Finally, we can perform the clustering:
  193. >>> Z = single(y)
  194. >>> Z
  195. array([[ 0., 1., 1., 2.],
  196. [ 2., 12., 1., 3.],
  197. [ 3., 4., 1., 2.],
  198. [ 5., 14., 1., 3.],
  199. [ 6., 7., 1., 2.],
  200. [ 8., 16., 1., 3.],
  201. [ 9., 10., 1., 2.],
  202. [11., 18., 1., 3.],
  203. [13., 15., 2., 6.],
  204. [17., 20., 2., 9.],
  205. [19., 21., 2., 12.]])
  206. The linkage matrix ``Z`` represents a dendrogram - see
  207. `scipy.cluster.hierarchy.linkage` for a detailed explanation of its
  208. contents.
  209. We can use `scipy.cluster.hierarchy.fcluster` to see to which cluster
  210. each initial point would belong given a distance threshold:
  211. >>> fcluster(Z, 0.9, criterion='distance')
  212. array([ 7, 8, 9, 10, 11, 12, 4, 5, 6, 1, 2, 3], dtype=int32)
  213. >>> fcluster(Z, 1, criterion='distance')
  214. array([3, 3, 3, 4, 4, 4, 2, 2, 2, 1, 1, 1], dtype=int32)
  215. >>> fcluster(Z, 2, criterion='distance')
  216. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  217. Also, `scipy.cluster.hierarchy.dendrogram` can be used to generate a
  218. plot of the dendrogram.
  219. """
  220. return linkage(y, method='single', metric='euclidean')
  221. def complete(y):
  222. """
  223. Perform complete/max/farthest point linkage on a condensed distance matrix.
  224. Parameters
  225. ----------
  226. y : ndarray
  227. The upper triangular of the distance matrix. The result of
  228. ``pdist`` is returned in this form.
  229. Returns
  230. -------
  231. Z : ndarray
  232. A linkage matrix containing the hierarchical clustering. See
  233. the `linkage` function documentation for more information
  234. on its structure.
  235. See Also
  236. --------
  237. linkage : for advanced creation of hierarchical clusterings.
  238. scipy.spatial.distance.pdist : pairwise distance metrics
  239. Examples
  240. --------
  241. >>> from scipy.cluster.hierarchy import complete, fcluster
  242. >>> from scipy.spatial.distance import pdist
  243. First, we need a toy dataset to play with::
  244. x x x x
  245. x x
  246. x x
  247. x x x x
  248. >>> X = [[0, 0], [0, 1], [1, 0],
  249. ... [0, 4], [0, 3], [1, 4],
  250. ... [4, 0], [3, 0], [4, 1],
  251. ... [4, 4], [3, 4], [4, 3]]
  252. Then, we get a condensed distance matrix from this dataset:
  253. >>> y = pdist(X)
  254. Finally, we can perform the clustering:
  255. >>> Z = complete(y)
  256. >>> Z
  257. array([[ 0. , 1. , 1. , 2. ],
  258. [ 3. , 4. , 1. , 2. ],
  259. [ 6. , 7. , 1. , 2. ],
  260. [ 9. , 10. , 1. , 2. ],
  261. [ 2. , 12. , 1.41421356, 3. ],
  262. [ 5. , 13. , 1.41421356, 3. ],
  263. [ 8. , 14. , 1.41421356, 3. ],
  264. [11. , 15. , 1.41421356, 3. ],
  265. [16. , 17. , 4.12310563, 6. ],
  266. [18. , 19. , 4.12310563, 6. ],
  267. [20. , 21. , 5.65685425, 12. ]])
  268. The linkage matrix ``Z`` represents a dendrogram - see
  269. `scipy.cluster.hierarchy.linkage` for a detailed explanation of its
  270. contents.
  271. We can use `scipy.cluster.hierarchy.fcluster` to see to which cluster
  272. each initial point would belong given a distance threshold:
  273. >>> fcluster(Z, 0.9, criterion='distance')
  274. array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype=int32)
  275. >>> fcluster(Z, 1.5, criterion='distance')
  276. array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=int32)
  277. >>> fcluster(Z, 4.5, criterion='distance')
  278. array([1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2], dtype=int32)
  279. >>> fcluster(Z, 6, criterion='distance')
  280. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  281. Also, `scipy.cluster.hierarchy.dendrogram` can be used to generate a
  282. plot of the dendrogram.
  283. """
  284. return linkage(y, method='complete', metric='euclidean')
  285. def average(y):
  286. """
  287. Perform average/UPGMA linkage on a condensed distance matrix.
  288. Parameters
  289. ----------
  290. y : ndarray
  291. The upper triangular of the distance matrix. The result of
  292. ``pdist`` is returned in this form.
  293. Returns
  294. -------
  295. Z : ndarray
  296. A linkage matrix containing the hierarchical clustering. See
  297. `linkage` for more information on its structure.
  298. See Also
  299. --------
  300. linkage : for advanced creation of hierarchical clusterings.
  301. scipy.spatial.distance.pdist : pairwise distance metrics
  302. Examples
  303. --------
  304. >>> from scipy.cluster.hierarchy import average, fcluster
  305. >>> from scipy.spatial.distance import pdist
  306. First, we need a toy dataset to play with::
  307. x x x x
  308. x x
  309. x x
  310. x x x x
  311. >>> X = [[0, 0], [0, 1], [1, 0],
  312. ... [0, 4], [0, 3], [1, 4],
  313. ... [4, 0], [3, 0], [4, 1],
  314. ... [4, 4], [3, 4], [4, 3]]
  315. Then, we get a condensed distance matrix from this dataset:
  316. >>> y = pdist(X)
  317. Finally, we can perform the clustering:
  318. >>> Z = average(y)
  319. >>> Z
  320. array([[ 0. , 1. , 1. , 2. ],
  321. [ 3. , 4. , 1. , 2. ],
  322. [ 6. , 7. , 1. , 2. ],
  323. [ 9. , 10. , 1. , 2. ],
  324. [ 2. , 12. , 1.20710678, 3. ],
  325. [ 5. , 13. , 1.20710678, 3. ],
  326. [ 8. , 14. , 1.20710678, 3. ],
  327. [11. , 15. , 1.20710678, 3. ],
  328. [16. , 17. , 3.39675184, 6. ],
  329. [18. , 19. , 3.39675184, 6. ],
  330. [20. , 21. , 4.09206523, 12. ]])
  331. The linkage matrix ``Z`` represents a dendrogram - see
  332. `scipy.cluster.hierarchy.linkage` for a detailed explanation of its
  333. contents.
  334. We can use `scipy.cluster.hierarchy.fcluster` to see to which cluster
  335. each initial point would belong given a distance threshold:
  336. >>> fcluster(Z, 0.9, criterion='distance')
  337. array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype=int32)
  338. >>> fcluster(Z, 1.5, criterion='distance')
  339. array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=int32)
  340. >>> fcluster(Z, 4, criterion='distance')
  341. array([1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2], dtype=int32)
  342. >>> fcluster(Z, 6, criterion='distance')
  343. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  344. Also, `scipy.cluster.hierarchy.dendrogram` can be used to generate a
  345. plot of the dendrogram.
  346. """
  347. return linkage(y, method='average', metric='euclidean')
  348. def weighted(y):
  349. """
  350. Perform weighted/WPGMA linkage on the condensed distance matrix.
  351. See `linkage` for more information on the return
  352. structure and algorithm.
  353. Parameters
  354. ----------
  355. y : ndarray
  356. The upper triangular of the distance matrix. The result of
  357. ``pdist`` is returned in this form.
  358. Returns
  359. -------
  360. Z : ndarray
  361. A linkage matrix containing the hierarchical clustering. See
  362. `linkage` for more information on its structure.
  363. See Also
  364. --------
  365. linkage : for advanced creation of hierarchical clusterings.
  366. scipy.spatial.distance.pdist : pairwise distance metrics
  367. Examples
  368. --------
  369. >>> from scipy.cluster.hierarchy import weighted, fcluster
  370. >>> from scipy.spatial.distance import pdist
  371. First, we need a toy dataset to play with::
  372. x x x x
  373. x x
  374. x x
  375. x x x x
  376. >>> X = [[0, 0], [0, 1], [1, 0],
  377. ... [0, 4], [0, 3], [1, 4],
  378. ... [4, 0], [3, 0], [4, 1],
  379. ... [4, 4], [3, 4], [4, 3]]
  380. Then, we get a condensed distance matrix from this dataset:
  381. >>> y = pdist(X)
  382. Finally, we can perform the clustering:
  383. >>> Z = weighted(y)
  384. >>> Z
  385. array([[ 0. , 1. , 1. , 2. ],
  386. [ 6. , 7. , 1. , 2. ],
  387. [ 3. , 4. , 1. , 2. ],
  388. [ 9. , 11. , 1. , 2. ],
  389. [ 2. , 12. , 1.20710678, 3. ],
  390. [ 8. , 13. , 1.20710678, 3. ],
  391. [ 5. , 14. , 1.20710678, 3. ],
  392. [10. , 15. , 1.20710678, 3. ],
  393. [18. , 19. , 3.05595762, 6. ],
  394. [16. , 17. , 3.32379407, 6. ],
  395. [20. , 21. , 4.06357713, 12. ]])
  396. The linkage matrix ``Z`` represents a dendrogram - see
  397. `scipy.cluster.hierarchy.linkage` for a detailed explanation of its
  398. contents.
  399. We can use `scipy.cluster.hierarchy.fcluster` to see to which cluster
  400. each initial point would belong given a distance threshold:
  401. >>> fcluster(Z, 0.9, criterion='distance')
  402. array([ 7, 8, 9, 1, 2, 3, 10, 11, 12, 4, 6, 5], dtype=int32)
  403. >>> fcluster(Z, 1.5, criterion='distance')
  404. array([3, 3, 3, 1, 1, 1, 4, 4, 4, 2, 2, 2], dtype=int32)
  405. >>> fcluster(Z, 4, criterion='distance')
  406. array([2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1], dtype=int32)
  407. >>> fcluster(Z, 6, criterion='distance')
  408. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  409. Also, `scipy.cluster.hierarchy.dendrogram` can be used to generate a
  410. plot of the dendrogram.
  411. """
  412. return linkage(y, method='weighted', metric='euclidean')
  413. def centroid(y):
  414. """
  415. Perform centroid/UPGMC linkage.
  416. See `linkage` for more information on the input matrix,
  417. return structure, and algorithm.
  418. The following are common calling conventions:
  419. 1. ``Z = centroid(y)``
  420. Performs centroid/UPGMC linkage on the condensed distance
  421. matrix ``y``.
  422. 2. ``Z = centroid(X)``
  423. Performs centroid/UPGMC linkage on the observation matrix ``X``
  424. using Euclidean distance as the distance metric.
  425. Parameters
  426. ----------
  427. y : ndarray
  428. A condensed distance matrix. A condensed
  429. distance matrix is a flat array containing the upper
  430. triangular of the distance matrix. This is the form that
  431. ``pdist`` returns. Alternatively, a collection of
  432. m observation vectors in n dimensions may be passed as
  433. an m by n array.
  434. Returns
  435. -------
  436. Z : ndarray
  437. A linkage matrix containing the hierarchical clustering. See
  438. the `linkage` function documentation for more information
  439. on its structure.
  440. See Also
  441. --------
  442. linkage : for advanced creation of hierarchical clusterings.
  443. scipy.spatial.distance.pdist : pairwise distance metrics
  444. Examples
  445. --------
  446. >>> from scipy.cluster.hierarchy import centroid, fcluster
  447. >>> from scipy.spatial.distance import pdist
  448. First, we need a toy dataset to play with::
  449. x x x x
  450. x x
  451. x x
  452. x x x x
  453. >>> X = [[0, 0], [0, 1], [1, 0],
  454. ... [0, 4], [0, 3], [1, 4],
  455. ... [4, 0], [3, 0], [4, 1],
  456. ... [4, 4], [3, 4], [4, 3]]
  457. Then, we get a condensed distance matrix from this dataset:
  458. >>> y = pdist(X)
  459. Finally, we can perform the clustering:
  460. >>> Z = centroid(y)
  461. >>> Z
  462. array([[ 0. , 1. , 1. , 2. ],
  463. [ 3. , 4. , 1. , 2. ],
  464. [ 9. , 10. , 1. , 2. ],
  465. [ 6. , 7. , 1. , 2. ],
  466. [ 2. , 12. , 1.11803399, 3. ],
  467. [ 5. , 13. , 1.11803399, 3. ],
  468. [ 8. , 15. , 1.11803399, 3. ],
  469. [11. , 14. , 1.11803399, 3. ],
  470. [18. , 19. , 3.33333333, 6. ],
  471. [16. , 17. , 3.33333333, 6. ],
  472. [20. , 21. , 3.33333333, 12. ]])
  473. The linkage matrix ``Z`` represents a dendrogram - see
  474. `scipy.cluster.hierarchy.linkage` for a detailed explanation of its
  475. contents.
  476. We can use `scipy.cluster.hierarchy.fcluster` to see to which cluster
  477. each initial point would belong given a distance threshold:
  478. >>> fcluster(Z, 0.9, criterion='distance')
  479. array([ 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6], dtype=int32)
  480. >>> fcluster(Z, 1.1, criterion='distance')
  481. array([5, 5, 6, 7, 7, 8, 1, 1, 2, 3, 3, 4], dtype=int32)
  482. >>> fcluster(Z, 2, criterion='distance')
  483. array([3, 3, 3, 4, 4, 4, 1, 1, 1, 2, 2, 2], dtype=int32)
  484. >>> fcluster(Z, 4, criterion='distance')
  485. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  486. Also, `scipy.cluster.hierarchy.dendrogram` can be used to generate a
  487. plot of the dendrogram.
  488. """
  489. return linkage(y, method='centroid', metric='euclidean')
  490. def median(y):
  491. """
  492. Perform median/WPGMC linkage.
  493. See `linkage` for more information on the return structure
  494. and algorithm.
  495. The following are common calling conventions:
  496. 1. ``Z = median(y)``
  497. Performs median/WPGMC linkage on the condensed distance matrix
  498. ``y``. See ``linkage`` for more information on the return
  499. structure and algorithm.
  500. 2. ``Z = median(X)``
  501. Performs median/WPGMC linkage on the observation matrix ``X``
  502. using Euclidean distance as the distance metric. See `linkage`
  503. for more information on the return structure and algorithm.
  504. Parameters
  505. ----------
  506. y : ndarray
  507. A condensed distance matrix. A condensed
  508. distance matrix is a flat array containing the upper
  509. triangular of the distance matrix. This is the form that
  510. ``pdist`` returns. Alternatively, a collection of
  511. m observation vectors in n dimensions may be passed as
  512. an m by n array.
  513. Returns
  514. -------
  515. Z : ndarray
  516. The hierarchical clustering encoded as a linkage matrix.
  517. See Also
  518. --------
  519. linkage : for advanced creation of hierarchical clusterings.
  520. scipy.spatial.distance.pdist : pairwise distance metrics
  521. Examples
  522. --------
  523. >>> from scipy.cluster.hierarchy import median, fcluster
  524. >>> from scipy.spatial.distance import pdist
  525. First, we need a toy dataset to play with::
  526. x x x x
  527. x x
  528. x x
  529. x x x x
  530. >>> X = [[0, 0], [0, 1], [1, 0],
  531. ... [0, 4], [0, 3], [1, 4],
  532. ... [4, 0], [3, 0], [4, 1],
  533. ... [4, 4], [3, 4], [4, 3]]
  534. Then, we get a condensed distance matrix from this dataset:
  535. >>> y = pdist(X)
  536. Finally, we can perform the clustering:
  537. >>> Z = median(y)
  538. >>> Z
  539. array([[ 0. , 1. , 1. , 2. ],
  540. [ 3. , 4. , 1. , 2. ],
  541. [ 9. , 10. , 1. , 2. ],
  542. [ 6. , 7. , 1. , 2. ],
  543. [ 2. , 12. , 1.11803399, 3. ],
  544. [ 5. , 13. , 1.11803399, 3. ],
  545. [ 8. , 15. , 1.11803399, 3. ],
  546. [11. , 14. , 1.11803399, 3. ],
  547. [18. , 19. , 3. , 6. ],
  548. [16. , 17. , 3.5 , 6. ],
  549. [20. , 21. , 3.25 , 12. ]])
  550. The linkage matrix ``Z`` represents a dendrogram - see
  551. `scipy.cluster.hierarchy.linkage` for a detailed explanation of its
  552. contents.
  553. We can use `scipy.cluster.hierarchy.fcluster` to see to which cluster
  554. each initial point would belong given a distance threshold:
  555. >>> fcluster(Z, 0.9, criterion='distance')
  556. array([ 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6], dtype=int32)
  557. >>> fcluster(Z, 1.1, criterion='distance')
  558. array([5, 5, 6, 7, 7, 8, 1, 1, 2, 3, 3, 4], dtype=int32)
  559. >>> fcluster(Z, 2, criterion='distance')
  560. array([3, 3, 3, 4, 4, 4, 1, 1, 1, 2, 2, 2], dtype=int32)
  561. >>> fcluster(Z, 4, criterion='distance')
  562. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  563. Also, `scipy.cluster.hierarchy.dendrogram` can be used to generate a
  564. plot of the dendrogram.
  565. """
  566. return linkage(y, method='median', metric='euclidean')
  567. def ward(y):
  568. """
  569. Perform Ward's linkage on a condensed distance matrix.
  570. See `linkage` for more information on the return structure
  571. and algorithm.
  572. The following are common calling conventions:
  573. 1. ``Z = ward(y)``
  574. Performs Ward's linkage on the condensed distance matrix ``y``.
  575. 2. ``Z = ward(X)``
  576. Performs Ward's linkage on the observation matrix ``X`` using
  577. Euclidean distance as the distance metric.
  578. Parameters
  579. ----------
  580. y : ndarray
  581. A condensed distance matrix. A condensed
  582. distance matrix is a flat array containing the upper
  583. triangular of the distance matrix. This is the form that
  584. ``pdist`` returns. Alternatively, a collection of
  585. m observation vectors in n dimensions may be passed as
  586. an m by n array.
  587. Returns
  588. -------
  589. Z : ndarray
  590. The hierarchical clustering encoded as a linkage matrix. See
  591. `linkage` for more information on the return structure and
  592. algorithm.
  593. See Also
  594. --------
  595. linkage : for advanced creation of hierarchical clusterings.
  596. scipy.spatial.distance.pdist : pairwise distance metrics
  597. Examples
  598. --------
  599. >>> from scipy.cluster.hierarchy import ward, fcluster
  600. >>> from scipy.spatial.distance import pdist
  601. First, we need a toy dataset to play with::
  602. x x x x
  603. x x
  604. x x
  605. x x x x
  606. >>> X = [[0, 0], [0, 1], [1, 0],
  607. ... [0, 4], [0, 3], [1, 4],
  608. ... [4, 0], [3, 0], [4, 1],
  609. ... [4, 4], [3, 4], [4, 3]]
  610. Then, we get a condensed distance matrix from this dataset:
  611. >>> y = pdist(X)
  612. Finally, we can perform the clustering:
  613. >>> Z = ward(y)
  614. >>> Z
  615. array([[ 0. , 1. , 1. , 2. ],
  616. [ 3. , 4. , 1. , 2. ],
  617. [ 6. , 7. , 1. , 2. ],
  618. [ 9. , 10. , 1. , 2. ],
  619. [ 2. , 12. , 1.29099445, 3. ],
  620. [ 5. , 13. , 1.29099445, 3. ],
  621. [ 8. , 14. , 1.29099445, 3. ],
  622. [11. , 15. , 1.29099445, 3. ],
  623. [16. , 17. , 5.77350269, 6. ],
  624. [18. , 19. , 5.77350269, 6. ],
  625. [20. , 21. , 8.16496581, 12. ]])
  626. The linkage matrix ``Z`` represents a dendrogram - see
  627. `scipy.cluster.hierarchy.linkage` for a detailed explanation of its
  628. contents.
  629. We can use `scipy.cluster.hierarchy.fcluster` to see to which cluster
  630. each initial point would belong given a distance threshold:
  631. >>> fcluster(Z, 0.9, criterion='distance')
  632. array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype=int32)
  633. >>> fcluster(Z, 1.1, criterion='distance')
  634. array([1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8], dtype=int32)
  635. >>> fcluster(Z, 3, criterion='distance')
  636. array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=int32)
  637. >>> fcluster(Z, 9, criterion='distance')
  638. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  639. Also, `scipy.cluster.hierarchy.dendrogram` can be used to generate a
  640. plot of the dendrogram.
  641. """
  642. return linkage(y, method='ward', metric='euclidean')
  643. def linkage(y, method='single', metric='euclidean', optimal_ordering=False):
  644. """
  645. Perform hierarchical/agglomerative clustering.
  646. The input y may be either a 1-D condensed distance matrix
  647. or a 2-D array of observation vectors.
  648. If y is a 1-D condensed distance matrix,
  649. then y must be a :math:`\\binom{n}{2}` sized
  650. vector, where n is the number of original observations paired
  651. in the distance matrix. The behavior of this function is very
  652. similar to the MATLAB linkage function.
  653. A :math:`(n-1)` by 4 matrix ``Z`` is returned. At the
  654. :math:`i`-th iteration, clusters with indices ``Z[i, 0]`` and
  655. ``Z[i, 1]`` are combined to form cluster :math:`n + i`. A
  656. cluster with an index less than :math:`n` corresponds to one of
  657. the :math:`n` original observations. The distance between
  658. clusters ``Z[i, 0]`` and ``Z[i, 1]`` is given by ``Z[i, 2]``. The
  659. fourth value ``Z[i, 3]`` represents the number of original
  660. observations in the newly formed cluster.
  661. The following linkage methods are used to compute the distance
  662. :math:`d(s, t)` between two clusters :math:`s` and
  663. :math:`t`. The algorithm begins with a forest of clusters that
  664. have yet to be used in the hierarchy being formed. When two
  665. clusters :math:`s` and :math:`t` from this forest are combined
  666. into a single cluster :math:`u`, :math:`s` and :math:`t` are
  667. removed from the forest, and :math:`u` is added to the
  668. forest. When only one cluster remains in the forest, the algorithm
  669. stops, and this cluster becomes the root.
  670. A distance matrix is maintained at each iteration. The ``d[i,j]``
  671. entry corresponds to the distance between cluster :math:`i` and
  672. :math:`j` in the original forest.
  673. At each iteration, the algorithm must update the distance matrix
  674. to reflect the distance of the newly formed cluster u with the
  675. remaining clusters in the forest.
  676. Suppose there are :math:`|u|` original observations
  677. :math:`u[0], \\ldots, u[|u|-1]` in cluster :math:`u` and
  678. :math:`|v|` original objects :math:`v[0], \\ldots, v[|v|-1]` in
  679. cluster :math:`v`. Recall, :math:`s` and :math:`t` are
  680. combined to form cluster :math:`u`. Let :math:`v` be any
  681. remaining cluster in the forest that is not :math:`u`.
  682. The following are methods for calculating the distance between the
  683. newly formed cluster :math:`u` and each :math:`v`.
  684. * method='single' assigns
  685. .. math::
  686. d(u,v) = \\min(dist(u[i],v[j]))
  687. for all points :math:`i` in cluster :math:`u` and
  688. :math:`j` in cluster :math:`v`. This is also known as the
  689. Nearest Point Algorithm.
  690. * method='complete' assigns
  691. .. math::
  692. d(u, v) = \\max(dist(u[i],v[j]))
  693. for all points :math:`i` in cluster u and :math:`j` in
  694. cluster :math:`v`. This is also known by the Farthest Point
  695. Algorithm or Voor Hees Algorithm.
  696. * method='average' assigns
  697. .. math::
  698. d(u,v) = \\sum_{ij} \\frac{d(u[i], v[j])}
  699. {(|u|*|v|)}
  700. for all points :math:`i` and :math:`j` where :math:`|u|`
  701. and :math:`|v|` are the cardinalities of clusters :math:`u`
  702. and :math:`v`, respectively. This is also called the UPGMA
  703. algorithm.
  704. * method='weighted' assigns
  705. .. math::
  706. d(u,v) = (dist(s,v) + dist(t,v))/2
  707. where cluster u was formed with cluster s and t and v
  708. is a remaining cluster in the forest (also called WPGMA).
  709. * method='centroid' assigns
  710. .. math::
  711. dist(s,t) = ||c_s-c_t||_2
  712. where :math:`c_s` and :math:`c_t` are the centroids of
  713. clusters :math:`s` and :math:`t`, respectively. When two
  714. clusters :math:`s` and :math:`t` are combined into a new
  715. cluster :math:`u`, the new centroid is computed over all the
  716. original objects in clusters :math:`s` and :math:`t`. The
  717. distance then becomes the Euclidean distance between the
  718. centroid of :math:`u` and the centroid of a remaining cluster
  719. :math:`v` in the forest. This is also known as the UPGMC
  720. algorithm.
  721. * method='median' assigns :math:`d(s,t)` like the ``centroid``
  722. method. When two clusters :math:`s` and :math:`t` are combined
  723. into a new cluster :math:`u`, the average of centroids s and t
  724. give the new centroid :math:`u`. This is also known as the
  725. WPGMC algorithm.
  726. * method='ward' uses the Ward variance minimization algorithm.
  727. The new entry :math:`d(u,v)` is computed as follows,
  728. .. math::
  729. d(u,v) = \\sqrt{\\frac{|v|+|s|}
  730. {T}d(v,s)^2
  731. + \\frac{|v|+|t|}
  732. {T}d(v,t)^2
  733. - \\frac{|v|}
  734. {T}d(s,t)^2}
  735. where :math:`u` is the newly joined cluster consisting of
  736. clusters :math:`s` and :math:`t`, :math:`v` is an unused
  737. cluster in the forest, :math:`T=|v|+|s|+|t|`, and
  738. :math:`|*|` is the cardinality of its argument. This is also
  739. known as the incremental algorithm.
  740. Warning: When the minimum distance pair in the forest is chosen, there
  741. may be two or more pairs with the same minimum distance. This
  742. implementation may choose a different minimum than the MATLAB
  743. version.
  744. Parameters
  745. ----------
  746. y : ndarray
  747. A condensed distance matrix. A condensed distance matrix
  748. is a flat array containing the upper triangular of the distance matrix.
  749. This is the form that ``pdist`` returns. Alternatively, a collection of
  750. :math:`m` observation vectors in :math:`n` dimensions may be passed as
  751. an :math:`m` by :math:`n` array. All elements of the condensed distance
  752. matrix must be finite, i.e., no NaNs or infs.
  753. method : str, optional
  754. The linkage algorithm to use. See the ``Linkage Methods`` section below
  755. for full descriptions.
  756. metric : str or function, optional
  757. The distance metric to use in the case that y is a collection of
  758. observation vectors; ignored otherwise. See the ``pdist``
  759. function for a list of valid distance metrics. A custom distance
  760. function can also be used.
  761. optimal_ordering : bool, optional
  762. If True, the linkage matrix will be reordered so that the distance
  763. between successive leaves is minimal. This results in a more intuitive
  764. tree structure when the data are visualized. defaults to False, because
  765. this algorithm can be slow, particularly on large datasets [2]_. See
  766. also the `optimal_leaf_ordering` function.
  767. .. versionadded:: 1.0.0
  768. Returns
  769. -------
  770. Z : ndarray
  771. The hierarchical clustering encoded as a linkage matrix.
  772. Notes
  773. -----
  774. 1. For method 'single', an optimized algorithm based on minimum spanning
  775. tree is implemented. It has time complexity :math:`O(n^2)`.
  776. For methods 'complete', 'average', 'weighted' and 'ward', an algorithm
  777. called nearest-neighbors chain is implemented. It also has time
  778. complexity :math:`O(n^2)`.
  779. For other methods, a naive algorithm is implemented with :math:`O(n^3)`
  780. time complexity.
  781. All algorithms use :math:`O(n^2)` memory.
  782. Refer to [1]_ for details about the algorithms.
  783. 2. Methods 'centroid', 'median', and 'ward' are correctly defined only if
  784. Euclidean pairwise metric is used. If `y` is passed as precomputed
  785. pairwise distances, then it is the user's responsibility to assure that
  786. these distances are in fact Euclidean, otherwise the produced result
  787. will be incorrect.
  788. See Also
  789. --------
  790. scipy.spatial.distance.pdist : pairwise distance metrics
  791. References
  792. ----------
  793. .. [1] Daniel Mullner, "Modern hierarchical, agglomerative clustering
  794. algorithms", :arXiv:`1109.2378v1`.
  795. .. [2] Ziv Bar-Joseph, David K. Gifford, Tommi S. Jaakkola, "Fast optimal
  796. leaf ordering for hierarchical clustering", 2001. Bioinformatics
  797. :doi:`10.1093/bioinformatics/17.suppl_1.S22`
  798. Examples
  799. --------
  800. >>> from scipy.cluster.hierarchy import dendrogram, linkage
  801. >>> from matplotlib import pyplot as plt
  802. >>> X = [[i] for i in [2, 8, 0, 4, 1, 9, 9, 0]]
  803. >>> Z = linkage(X, 'ward')
  804. >>> fig = plt.figure(figsize=(25, 10))
  805. >>> dn = dendrogram(Z)
  806. >>> Z = linkage(X, 'single')
  807. >>> fig = plt.figure(figsize=(25, 10))
  808. >>> dn = dendrogram(Z)
  809. >>> plt.show()
  810. """
  811. if method not in _LINKAGE_METHODS:
  812. raise ValueError("Invalid method: {0}".format(method))
  813. y = _convert_to_double(np.asarray(y, order='c'))
  814. if y.ndim == 1:
  815. distance.is_valid_y(y, throw=True, name='y')
  816. [y] = _copy_arrays_if_base_present([y])
  817. elif y.ndim == 2:
  818. if method in _EUCLIDEAN_METHODS and metric != 'euclidean':
  819. raise ValueError("Method '{0}' requires the distance metric "
  820. "to be Euclidean".format(method))
  821. if y.shape[0] == y.shape[1] and np.allclose(np.diag(y), 0):
  822. if np.all(y >= 0) and np.allclose(y, y.T):
  823. _warning('The symmetric non-negative hollow observation '
  824. 'matrix looks suspiciously like an uncondensed '
  825. 'distance matrix')
  826. y = distance.pdist(y, metric)
  827. else:
  828. raise ValueError("`y` must be 1 or 2 dimensional.")
  829. if not np.all(np.isfinite(y)):
  830. raise ValueError("The condensed distance matrix must contain only "
  831. "finite values.")
  832. n = int(distance.num_obs_y(y))
  833. method_code = _LINKAGE_METHODS[method]
  834. if method == 'single':
  835. result = _hierarchy.mst_single_linkage(y, n)
  836. elif method in ['complete', 'average', 'weighted', 'ward']:
  837. result = _hierarchy.nn_chain(y, n, method_code)
  838. else:
  839. result = _hierarchy.fast_linkage(y, n, method_code)
  840. if optimal_ordering:
  841. return optimal_leaf_ordering(result, y)
  842. else:
  843. return result
  844. class ClusterNode:
  845. """
  846. A tree node class for representing a cluster.
  847. Leaf nodes correspond to original observations, while non-leaf nodes
  848. correspond to non-singleton clusters.
  849. The `to_tree` function converts a matrix returned by the linkage
  850. function into an easy-to-use tree representation.
  851. All parameter names are also attributes.
  852. Parameters
  853. ----------
  854. id : int
  855. The node id.
  856. left : ClusterNode instance, optional
  857. The left child tree node.
  858. right : ClusterNode instance, optional
  859. The right child tree node.
  860. dist : float, optional
  861. Distance for this cluster in the linkage matrix.
  862. count : int, optional
  863. The number of samples in this cluster.
  864. See Also
  865. --------
  866. to_tree : for converting a linkage matrix ``Z`` into a tree object.
  867. """
  868. def __init__(self, id, left=None, right=None, dist=0, count=1):
  869. if id < 0:
  870. raise ValueError('The id must be non-negative.')
  871. if dist < 0:
  872. raise ValueError('The distance must be non-negative.')
  873. if (left is None and right is not None) or \
  874. (left is not None and right is None):
  875. raise ValueError('Only full or proper binary trees are permitted.'
  876. ' This node has one child.')
  877. if count < 1:
  878. raise ValueError('A cluster must contain at least one original '
  879. 'observation.')
  880. self.id = id
  881. self.left = left
  882. self.right = right
  883. self.dist = dist
  884. if self.left is None:
  885. self.count = count
  886. else:
  887. self.count = left.count + right.count
  888. def __lt__(self, node):
  889. if not isinstance(node, ClusterNode):
  890. raise ValueError("Can't compare ClusterNode "
  891. "to type {}".format(type(node)))
  892. return self.dist < node.dist
  893. def __gt__(self, node):
  894. if not isinstance(node, ClusterNode):
  895. raise ValueError("Can't compare ClusterNode "
  896. "to type {}".format(type(node)))
  897. return self.dist > node.dist
  898. def __eq__(self, node):
  899. if not isinstance(node, ClusterNode):
  900. raise ValueError("Can't compare ClusterNode "
  901. "to type {}".format(type(node)))
  902. return self.dist == node.dist
  903. def get_id(self):
  904. """
  905. The identifier of the target node.
  906. For ``0 <= i < n``, `i` corresponds to original observation i.
  907. For ``n <= i < 2n-1``, `i` corresponds to non-singleton cluster formed
  908. at iteration ``i-n``.
  909. Returns
  910. -------
  911. id : int
  912. The identifier of the target node.
  913. """
  914. return self.id
  915. def get_count(self):
  916. """
  917. The number of leaf nodes (original observations) belonging to
  918. the cluster node nd. If the target node is a leaf, 1 is
  919. returned.
  920. Returns
  921. -------
  922. get_count : int
  923. The number of leaf nodes below the target node.
  924. """
  925. return self.count
  926. def get_left(self):
  927. """
  928. Return a reference to the left child tree object.
  929. Returns
  930. -------
  931. left : ClusterNode
  932. The left child of the target node. If the node is a leaf,
  933. None is returned.
  934. """
  935. return self.left
  936. def get_right(self):
  937. """
  938. Return a reference to the right child tree object.
  939. Returns
  940. -------
  941. right : ClusterNode
  942. The left child of the target node. If the node is a leaf,
  943. None is returned.
  944. """
  945. return self.right
  946. def is_leaf(self):
  947. """
  948. Return True if the target node is a leaf.
  949. Returns
  950. -------
  951. leafness : bool
  952. True if the target node is a leaf node.
  953. """
  954. return self.left is None
  955. def pre_order(self, func=(lambda x: x.id)):
  956. """
  957. Perform pre-order traversal without recursive function calls.
  958. When a leaf node is first encountered, ``func`` is called with
  959. the leaf node as its argument, and its result is appended to
  960. the list.
  961. For example, the statement::
  962. ids = root.pre_order(lambda x: x.id)
  963. returns a list of the node ids corresponding to the leaf nodes
  964. of the tree as they appear from left to right.
  965. Parameters
  966. ----------
  967. func : function
  968. Applied to each leaf ClusterNode object in the pre-order traversal.
  969. Given the ``i``-th leaf node in the pre-order traversal ``n[i]``,
  970. the result of ``func(n[i])`` is stored in ``L[i]``. If not
  971. provided, the index of the original observation to which the node
  972. corresponds is used.
  973. Returns
  974. -------
  975. L : list
  976. The pre-order traversal.
  977. """
  978. # Do a preorder traversal, caching the result. To avoid having to do
  979. # recursion, we'll store the previous index we've visited in a vector.
  980. n = self.count
  981. curNode = [None] * (2 * n)
  982. lvisited = set()
  983. rvisited = set()
  984. curNode[0] = self
  985. k = 0
  986. preorder = []
  987. while k >= 0:
  988. nd = curNode[k]
  989. ndid = nd.id
  990. if nd.is_leaf():
  991. preorder.append(func(nd))
  992. k = k - 1
  993. else:
  994. if ndid not in lvisited:
  995. curNode[k + 1] = nd.left
  996. lvisited.add(ndid)
  997. k = k + 1
  998. elif ndid not in rvisited:
  999. curNode[k + 1] = nd.right
  1000. rvisited.add(ndid)
  1001. k = k + 1
  1002. # If we've visited the left and right of this non-leaf
  1003. # node already, go up in the tree.
  1004. else:
  1005. k = k - 1
  1006. return preorder
  1007. _cnode_bare = ClusterNode(0)
  1008. _cnode_type = type(ClusterNode)
  1009. def _order_cluster_tree(Z):
  1010. """
  1011. Return clustering nodes in bottom-up order by distance.
  1012. Parameters
  1013. ----------
  1014. Z : scipy.cluster.linkage array
  1015. The linkage matrix.
  1016. Returns
  1017. -------
  1018. nodes : list
  1019. A list of ClusterNode objects.
  1020. """
  1021. q = deque()
  1022. tree = to_tree(Z)
  1023. q.append(tree)
  1024. nodes = []
  1025. while q:
  1026. node = q.popleft()
  1027. if not node.is_leaf():
  1028. bisect.insort_left(nodes, node)
  1029. q.append(node.get_right())
  1030. q.append(node.get_left())
  1031. return nodes
  1032. def cut_tree(Z, n_clusters=None, height=None):
  1033. """
  1034. Given a linkage matrix Z, return the cut tree.
  1035. Parameters
  1036. ----------
  1037. Z : scipy.cluster.linkage array
  1038. The linkage matrix.
  1039. n_clusters : array_like, optional
  1040. Number of clusters in the tree at the cut point.
  1041. height : array_like, optional
  1042. The height at which to cut the tree. Only possible for ultrametric
  1043. trees.
  1044. Returns
  1045. -------
  1046. cutree : array
  1047. An array indicating group membership at each agglomeration step. I.e.,
  1048. for a full cut tree, in the first column each data point is in its own
  1049. cluster. At the next step, two nodes are merged. Finally, all
  1050. singleton and non-singleton clusters are in one group. If `n_clusters`
  1051. or `height` are given, the columns correspond to the columns of
  1052. `n_clusters` or `height`.
  1053. Examples
  1054. --------
  1055. >>> from scipy import cluster
  1056. >>> import numpy as np
  1057. >>> from numpy.random import default_rng
  1058. >>> rng = default_rng()
  1059. >>> X = rng.random((50, 4))
  1060. >>> Z = cluster.hierarchy.ward(X)
  1061. >>> cutree = cluster.hierarchy.cut_tree(Z, n_clusters=[5, 10])
  1062. >>> cutree[:10]
  1063. array([[0, 0],
  1064. [1, 1],
  1065. [2, 2],
  1066. [3, 3],
  1067. [3, 4],
  1068. [2, 2],
  1069. [0, 0],
  1070. [1, 5],
  1071. [3, 6],
  1072. [4, 7]]) # random
  1073. """
  1074. nobs = num_obs_linkage(Z)
  1075. nodes = _order_cluster_tree(Z)
  1076. if height is not None and n_clusters is not None:
  1077. raise ValueError("At least one of either height or n_clusters "
  1078. "must be None")
  1079. elif height is None and n_clusters is None: # return the full cut tree
  1080. cols_idx = np.arange(nobs)
  1081. elif height is not None:
  1082. heights = np.array([x.dist for x in nodes])
  1083. cols_idx = np.searchsorted(heights, height)
  1084. else:
  1085. cols_idx = nobs - np.searchsorted(np.arange(nobs), n_clusters)
  1086. try:
  1087. n_cols = len(cols_idx)
  1088. except TypeError: # scalar
  1089. n_cols = 1
  1090. cols_idx = np.array([cols_idx])
  1091. groups = np.zeros((n_cols, nobs), dtype=int)
  1092. last_group = np.arange(nobs)
  1093. if 0 in cols_idx:
  1094. groups[0] = last_group
  1095. for i, node in enumerate(nodes):
  1096. idx = node.pre_order()
  1097. this_group = last_group.copy()
  1098. this_group[idx] = last_group[idx].min()
  1099. this_group[this_group > last_group[idx].max()] -= 1
  1100. if i + 1 in cols_idx:
  1101. groups[np.nonzero(i + 1 == cols_idx)[0]] = this_group
  1102. last_group = this_group
  1103. return groups.T
  1104. def to_tree(Z, rd=False):
  1105. """
  1106. Convert a linkage matrix into an easy-to-use tree object.
  1107. The reference to the root `ClusterNode` object is returned (by default).
  1108. Each `ClusterNode` object has a ``left``, ``right``, ``dist``, ``id``,
  1109. and ``count`` attribute. The left and right attributes point to
  1110. ClusterNode objects that were combined to generate the cluster.
  1111. If both are None then the `ClusterNode` object is a leaf node, its count
  1112. must be 1, and its distance is meaningless but set to 0.
  1113. *Note: This function is provided for the convenience of the library
  1114. user. ClusterNodes are not used as input to any of the functions in this
  1115. library.*
  1116. Parameters
  1117. ----------
  1118. Z : ndarray
  1119. The linkage matrix in proper form (see the `linkage`
  1120. function documentation).
  1121. rd : bool, optional
  1122. When False (default), a reference to the root `ClusterNode` object is
  1123. returned. Otherwise, a tuple ``(r, d)`` is returned. ``r`` is a
  1124. reference to the root node while ``d`` is a list of `ClusterNode`
  1125. objects - one per original entry in the linkage matrix plus entries
  1126. for all clustering steps. If a cluster id is
  1127. less than the number of samples ``n`` in the data that the linkage
  1128. matrix describes, then it corresponds to a singleton cluster (leaf
  1129. node).
  1130. See `linkage` for more information on the assignment of cluster ids
  1131. to clusters.
  1132. Returns
  1133. -------
  1134. tree : ClusterNode or tuple (ClusterNode, list of ClusterNode)
  1135. If ``rd`` is False, a `ClusterNode`.
  1136. If ``rd`` is True, a list of length ``2*n - 1``, with ``n`` the number
  1137. of samples. See the description of `rd` above for more details.
  1138. See Also
  1139. --------
  1140. linkage, is_valid_linkage, ClusterNode
  1141. Examples
  1142. --------
  1143. >>> import numpy as np
  1144. >>> from scipy.cluster import hierarchy
  1145. >>> rng = np.random.default_rng()
  1146. >>> x = rng.random((5, 2))
  1147. >>> Z = hierarchy.linkage(x)
  1148. >>> hierarchy.to_tree(Z)
  1149. <scipy.cluster.hierarchy.ClusterNode object at ...
  1150. >>> rootnode, nodelist = hierarchy.to_tree(Z, rd=True)
  1151. >>> rootnode
  1152. <scipy.cluster.hierarchy.ClusterNode object at ...
  1153. >>> len(nodelist)
  1154. 9
  1155. """
  1156. Z = np.asarray(Z, order='c')
  1157. is_valid_linkage(Z, throw=True, name='Z')
  1158. # Number of original objects is equal to the number of rows plus 1.
  1159. n = Z.shape[0] + 1
  1160. # Create a list full of None's to store the node objects
  1161. d = [None] * (n * 2 - 1)
  1162. # Create the nodes corresponding to the n original objects.
  1163. for i in range(0, n):
  1164. d[i] = ClusterNode(i)
  1165. nd = None
  1166. for i, row in enumerate(Z):
  1167. fi = int(row[0])
  1168. fj = int(row[1])
  1169. if fi > i + n:
  1170. raise ValueError(('Corrupt matrix Z. Index to derivative cluster '
  1171. 'is used before it is formed. See row %d, '
  1172. 'column 0') % fi)
  1173. if fj > i + n:
  1174. raise ValueError(('Corrupt matrix Z. Index to derivative cluster '
  1175. 'is used before it is formed. See row %d, '
  1176. 'column 1') % fj)
  1177. nd = ClusterNode(i + n, d[fi], d[fj], row[2])
  1178. # ^ id ^ left ^ right ^ dist
  1179. if row[3] != nd.count:
  1180. raise ValueError(('Corrupt matrix Z. The count Z[%d,3] is '
  1181. 'incorrect.') % i)
  1182. d[n + i] = nd
  1183. if rd:
  1184. return (nd, d)
  1185. else:
  1186. return nd
  1187. def optimal_leaf_ordering(Z, y, metric='euclidean'):
  1188. """
  1189. Given a linkage matrix Z and distance, reorder the cut tree.
  1190. Parameters
  1191. ----------
  1192. Z : ndarray
  1193. The hierarchical clustering encoded as a linkage matrix. See
  1194. `linkage` for more information on the return structure and
  1195. algorithm.
  1196. y : ndarray
  1197. The condensed distance matrix from which Z was generated.
  1198. Alternatively, a collection of m observation vectors in n
  1199. dimensions may be passed as an m by n array.
  1200. metric : str or function, optional
  1201. The distance metric to use in the case that y is a collection of
  1202. observation vectors; ignored otherwise. See the ``pdist``
  1203. function for a list of valid distance metrics. A custom distance
  1204. function can also be used.
  1205. Returns
  1206. -------
  1207. Z_ordered : ndarray
  1208. A copy of the linkage matrix Z, reordered to minimize the distance
  1209. between adjacent leaves.
  1210. Examples
  1211. --------
  1212. >>> import numpy as np
  1213. >>> from scipy.cluster import hierarchy
  1214. >>> rng = np.random.default_rng()
  1215. >>> X = rng.standard_normal((10, 10))
  1216. >>> Z = hierarchy.ward(X)
  1217. >>> hierarchy.leaves_list(Z)
  1218. array([0, 3, 1, 9, 2, 5, 7, 4, 6, 8], dtype=int32)
  1219. >>> hierarchy.leaves_list(hierarchy.optimal_leaf_ordering(Z, X))
  1220. array([3, 0, 2, 5, 7, 4, 8, 6, 9, 1], dtype=int32)
  1221. """
  1222. Z = np.asarray(Z, order='c')
  1223. is_valid_linkage(Z, throw=True, name='Z')
  1224. y = _convert_to_double(np.asarray(y, order='c'))
  1225. if y.ndim == 1:
  1226. distance.is_valid_y(y, throw=True, name='y')
  1227. [y] = _copy_arrays_if_base_present([y])
  1228. elif y.ndim == 2:
  1229. if y.shape[0] == y.shape[1] and np.allclose(np.diag(y), 0):
  1230. if np.all(y >= 0) and np.allclose(y, y.T):
  1231. _warning('The symmetric non-negative hollow observation '
  1232. 'matrix looks suspiciously like an uncondensed '
  1233. 'distance matrix')
  1234. y = distance.pdist(y, metric)
  1235. else:
  1236. raise ValueError("`y` must be 1 or 2 dimensional.")
  1237. if not np.all(np.isfinite(y)):
  1238. raise ValueError("The condensed distance matrix must contain only "
  1239. "finite values.")
  1240. return _optimal_leaf_ordering.optimal_leaf_ordering(Z, y)
  1241. def _convert_to_bool(X):
  1242. if X.dtype != bool:
  1243. X = X.astype(bool)
  1244. if not X.flags.contiguous:
  1245. X = X.copy()
  1246. return X
  1247. def _convert_to_double(X):
  1248. if X.dtype != np.double:
  1249. X = X.astype(np.double)
  1250. if not X.flags.contiguous:
  1251. X = X.copy()
  1252. return X
  1253. def cophenet(Z, Y=None):
  1254. """
  1255. Calculate the cophenetic distances between each observation in
  1256. the hierarchical clustering defined by the linkage ``Z``.
  1257. Suppose ``p`` and ``q`` are original observations in
  1258. disjoint clusters ``s`` and ``t``, respectively and
  1259. ``s`` and ``t`` are joined by a direct parent cluster
  1260. ``u``. The cophenetic distance between observations
  1261. ``i`` and ``j`` is simply the distance between
  1262. clusters ``s`` and ``t``.
  1263. Parameters
  1264. ----------
  1265. Z : ndarray
  1266. The hierarchical clustering encoded as an array
  1267. (see `linkage` function).
  1268. Y : ndarray (optional)
  1269. Calculates the cophenetic correlation coefficient ``c`` of a
  1270. hierarchical clustering defined by the linkage matrix `Z`
  1271. of a set of :math:`n` observations in :math:`m`
  1272. dimensions. `Y` is the condensed distance matrix from which
  1273. `Z` was generated.
  1274. Returns
  1275. -------
  1276. c : ndarray
  1277. The cophentic correlation distance (if ``Y`` is passed).
  1278. d : ndarray
  1279. The cophenetic distance matrix in condensed form. The
  1280. :math:`ij` th entry is the cophenetic distance between
  1281. original observations :math:`i` and :math:`j`.
  1282. See Also
  1283. --------
  1284. linkage :
  1285. for a description of what a linkage matrix is.
  1286. scipy.spatial.distance.squareform :
  1287. transforming condensed matrices into square ones.
  1288. Examples
  1289. --------
  1290. >>> from scipy.cluster.hierarchy import single, cophenet
  1291. >>> from scipy.spatial.distance import pdist, squareform
  1292. Given a dataset ``X`` and a linkage matrix ``Z``, the cophenetic distance
  1293. between two points of ``X`` is the distance between the largest two
  1294. distinct clusters that each of the points:
  1295. >>> X = [[0, 0], [0, 1], [1, 0],
  1296. ... [0, 4], [0, 3], [1, 4],
  1297. ... [4, 0], [3, 0], [4, 1],
  1298. ... [4, 4], [3, 4], [4, 3]]
  1299. ``X`` corresponds to this dataset ::
  1300. x x x x
  1301. x x
  1302. x x
  1303. x x x x
  1304. >>> Z = single(pdist(X))
  1305. >>> Z
  1306. array([[ 0., 1., 1., 2.],
  1307. [ 2., 12., 1., 3.],
  1308. [ 3., 4., 1., 2.],
  1309. [ 5., 14., 1., 3.],
  1310. [ 6., 7., 1., 2.],
  1311. [ 8., 16., 1., 3.],
  1312. [ 9., 10., 1., 2.],
  1313. [11., 18., 1., 3.],
  1314. [13., 15., 2., 6.],
  1315. [17., 20., 2., 9.],
  1316. [19., 21., 2., 12.]])
  1317. >>> cophenet(Z)
  1318. array([1., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2., 1., 2., 2., 2., 2., 2.,
  1319. 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 1., 1., 2., 2.,
  1320. 2., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2.,
  1321. 1., 1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 1., 1., 1.])
  1322. The output of the `scipy.cluster.hierarchy.cophenet` method is
  1323. represented in condensed form. We can use
  1324. `scipy.spatial.distance.squareform` to see the output as a
  1325. regular matrix (where each element ``ij`` denotes the cophenetic distance
  1326. between each ``i``, ``j`` pair of points in ``X``):
  1327. >>> squareform(cophenet(Z))
  1328. array([[0., 1., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
  1329. [1., 0., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
  1330. [1., 1., 0., 2., 2., 2., 2., 2., 2., 2., 2., 2.],
  1331. [2., 2., 2., 0., 1., 1., 2., 2., 2., 2., 2., 2.],
  1332. [2., 2., 2., 1., 0., 1., 2., 2., 2., 2., 2., 2.],
  1333. [2., 2., 2., 1., 1., 0., 2., 2., 2., 2., 2., 2.],
  1334. [2., 2., 2., 2., 2., 2., 0., 1., 1., 2., 2., 2.],
  1335. [2., 2., 2., 2., 2., 2., 1., 0., 1., 2., 2., 2.],
  1336. [2., 2., 2., 2., 2., 2., 1., 1., 0., 2., 2., 2.],
  1337. [2., 2., 2., 2., 2., 2., 2., 2., 2., 0., 1., 1.],
  1338. [2., 2., 2., 2., 2., 2., 2., 2., 2., 1., 0., 1.],
  1339. [2., 2., 2., 2., 2., 2., 2., 2., 2., 1., 1., 0.]])
  1340. In this example, the cophenetic distance between points on ``X`` that are
  1341. very close (i.e., in the same corner) is 1. For other pairs of points is 2,
  1342. because the points will be located in clusters at different
  1343. corners - thus, the distance between these clusters will be larger.
  1344. """
  1345. Z = np.asarray(Z, order='c')
  1346. is_valid_linkage(Z, throw=True, name='Z')
  1347. Zs = Z.shape
  1348. n = Zs[0] + 1
  1349. zz = np.zeros((n * (n-1)) // 2, dtype=np.double)
  1350. # Since the C code does not support striding using strides.
  1351. # The dimensions are used instead.
  1352. Z = _convert_to_double(Z)
  1353. _hierarchy.cophenetic_distances(Z, zz, int(n))
  1354. if Y is None:
  1355. return zz
  1356. Y = np.asarray(Y, order='c')
  1357. distance.is_valid_y(Y, throw=True, name='Y')
  1358. z = zz.mean()
  1359. y = Y.mean()
  1360. Yy = Y - y
  1361. Zz = zz - z
  1362. numerator = (Yy * Zz)
  1363. denomA = Yy**2
  1364. denomB = Zz**2
  1365. c = numerator.sum() / np.sqrt((denomA.sum() * denomB.sum()))
  1366. return (c, zz)
  1367. def inconsistent(Z, d=2):
  1368. r"""
  1369. Calculate inconsistency statistics on a linkage matrix.
  1370. Parameters
  1371. ----------
  1372. Z : ndarray
  1373. The :math:`(n-1)` by 4 matrix encoding the linkage (hierarchical
  1374. clustering). See `linkage` documentation for more information on its
  1375. form.
  1376. d : int, optional
  1377. The number of links up to `d` levels below each non-singleton cluster.
  1378. Returns
  1379. -------
  1380. R : ndarray
  1381. A :math:`(n-1)` by 4 matrix where the ``i``'th row contains the link
  1382. statistics for the non-singleton cluster ``i``. The link statistics are
  1383. computed over the link heights for links :math:`d` levels below the
  1384. cluster ``i``. ``R[i,0]`` and ``R[i,1]`` are the mean and standard
  1385. deviation of the link heights, respectively; ``R[i,2]`` is the number
  1386. of links included in the calculation; and ``R[i,3]`` is the
  1387. inconsistency coefficient,
  1388. .. math:: \frac{\mathtt{Z[i,2]} - \mathtt{R[i,0]}} {R[i,1]}
  1389. Notes
  1390. -----
  1391. This function behaves similarly to the MATLAB(TM) ``inconsistent``
  1392. function.
  1393. Examples
  1394. --------
  1395. >>> from scipy.cluster.hierarchy import inconsistent, linkage
  1396. >>> from matplotlib import pyplot as plt
  1397. >>> X = [[i] for i in [2, 8, 0, 4, 1, 9, 9, 0]]
  1398. >>> Z = linkage(X, 'ward')
  1399. >>> print(Z)
  1400. [[ 5. 6. 0. 2. ]
  1401. [ 2. 7. 0. 2. ]
  1402. [ 0. 4. 1. 2. ]
  1403. [ 1. 8. 1.15470054 3. ]
  1404. [ 9. 10. 2.12132034 4. ]
  1405. [ 3. 12. 4.11096096 5. ]
  1406. [11. 13. 14.07183949 8. ]]
  1407. >>> inconsistent(Z)
  1408. array([[ 0. , 0. , 1. , 0. ],
  1409. [ 0. , 0. , 1. , 0. ],
  1410. [ 1. , 0. , 1. , 0. ],
  1411. [ 0.57735027, 0.81649658, 2. , 0.70710678],
  1412. [ 1.04044011, 1.06123822, 3. , 1.01850858],
  1413. [ 3.11614065, 1.40688837, 2. , 0.70710678],
  1414. [ 6.44583366, 6.76770586, 3. , 1.12682288]])
  1415. """
  1416. Z = np.asarray(Z, order='c')
  1417. Zs = Z.shape
  1418. is_valid_linkage(Z, throw=True, name='Z')
  1419. if (not d == np.floor(d)) or d < 0:
  1420. raise ValueError('The second argument d must be a nonnegative '
  1421. 'integer value.')
  1422. # Since the C code does not support striding using strides.
  1423. # The dimensions are used instead.
  1424. [Z] = _copy_arrays_if_base_present([Z])
  1425. n = Zs[0] + 1
  1426. R = np.zeros((n - 1, 4), dtype=np.double)
  1427. _hierarchy.inconsistent(Z, R, int(n), int(d))
  1428. return R
  1429. def from_mlab_linkage(Z):
  1430. """
  1431. Convert a linkage matrix generated by MATLAB(TM) to a new
  1432. linkage matrix compatible with this module.
  1433. The conversion does two things:
  1434. * the indices are converted from ``1..N`` to ``0..(N-1)`` form,
  1435. and
  1436. * a fourth column ``Z[:,3]`` is added where ``Z[i,3]`` represents the
  1437. number of original observations (leaves) in the non-singleton
  1438. cluster ``i``.
  1439. This function is useful when loading in linkages from legacy data
  1440. files generated by MATLAB.
  1441. Parameters
  1442. ----------
  1443. Z : ndarray
  1444. A linkage matrix generated by MATLAB(TM).
  1445. Returns
  1446. -------
  1447. ZS : ndarray
  1448. A linkage matrix compatible with ``scipy.cluster.hierarchy``.
  1449. See Also
  1450. --------
  1451. linkage : for a description of what a linkage matrix is.
  1452. to_mlab_linkage : transform from SciPy to MATLAB format.
  1453. Examples
  1454. --------
  1455. >>> import numpy as np
  1456. >>> from scipy.cluster.hierarchy import ward, from_mlab_linkage
  1457. Given a linkage matrix in MATLAB format ``mZ``, we can use
  1458. `scipy.cluster.hierarchy.from_mlab_linkage` to import
  1459. it into SciPy format:
  1460. >>> mZ = np.array([[1, 2, 1], [4, 5, 1], [7, 8, 1],
  1461. ... [10, 11, 1], [3, 13, 1.29099445],
  1462. ... [6, 14, 1.29099445],
  1463. ... [9, 15, 1.29099445],
  1464. ... [12, 16, 1.29099445],
  1465. ... [17, 18, 5.77350269],
  1466. ... [19, 20, 5.77350269],
  1467. ... [21, 22, 8.16496581]])
  1468. >>> Z = from_mlab_linkage(mZ)
  1469. >>> Z
  1470. array([[ 0. , 1. , 1. , 2. ],
  1471. [ 3. , 4. , 1. , 2. ],
  1472. [ 6. , 7. , 1. , 2. ],
  1473. [ 9. , 10. , 1. , 2. ],
  1474. [ 2. , 12. , 1.29099445, 3. ],
  1475. [ 5. , 13. , 1.29099445, 3. ],
  1476. [ 8. , 14. , 1.29099445, 3. ],
  1477. [ 11. , 15. , 1.29099445, 3. ],
  1478. [ 16. , 17. , 5.77350269, 6. ],
  1479. [ 18. , 19. , 5.77350269, 6. ],
  1480. [ 20. , 21. , 8.16496581, 12. ]])
  1481. As expected, the linkage matrix ``Z`` returned includes an
  1482. additional column counting the number of original samples in
  1483. each cluster. Also, all cluster indices are reduced by 1
  1484. (MATLAB format uses 1-indexing, whereas SciPy uses 0-indexing).
  1485. """
  1486. Z = np.asarray(Z, dtype=np.double, order='c')
  1487. Zs = Z.shape
  1488. # If it's empty, return it.
  1489. if len(Zs) == 0 or (len(Zs) == 1 and Zs[0] == 0):
  1490. return Z.copy()
  1491. if len(Zs) != 2:
  1492. raise ValueError("The linkage array must be rectangular.")
  1493. # If it contains no rows, return it.
  1494. if Zs[0] == 0:
  1495. return Z.copy()
  1496. Zpart = Z.copy()
  1497. if Zpart[:, 0:2].min() != 1.0 and Zpart[:, 0:2].max() != 2 * Zs[0]:
  1498. raise ValueError('The format of the indices is not 1..N')
  1499. Zpart[:, 0:2] -= 1.0
  1500. CS = np.zeros((Zs[0],), dtype=np.double)
  1501. _hierarchy.calculate_cluster_sizes(Zpart, CS, int(Zs[0]) + 1)
  1502. return np.hstack([Zpart, CS.reshape(Zs[0], 1)])
  1503. def to_mlab_linkage(Z):
  1504. """
  1505. Convert a linkage matrix to a MATLAB(TM) compatible one.
  1506. Converts a linkage matrix ``Z`` generated by the linkage function
  1507. of this module to a MATLAB(TM) compatible one. The return linkage
  1508. matrix has the last column removed and the cluster indices are
  1509. converted to ``1..N`` indexing.
  1510. Parameters
  1511. ----------
  1512. Z : ndarray
  1513. A linkage matrix generated by ``scipy.cluster.hierarchy``.
  1514. Returns
  1515. -------
  1516. to_mlab_linkage : ndarray
  1517. A linkage matrix compatible with MATLAB(TM)'s hierarchical
  1518. clustering functions.
  1519. The return linkage matrix has the last column removed
  1520. and the cluster indices are converted to ``1..N`` indexing.
  1521. See Also
  1522. --------
  1523. linkage : for a description of what a linkage matrix is.
  1524. from_mlab_linkage : transform from Matlab to SciPy format.
  1525. Examples
  1526. --------
  1527. >>> from scipy.cluster.hierarchy import ward, to_mlab_linkage
  1528. >>> from scipy.spatial.distance import pdist
  1529. >>> X = [[0, 0], [0, 1], [1, 0],
  1530. ... [0, 4], [0, 3], [1, 4],
  1531. ... [4, 0], [3, 0], [4, 1],
  1532. ... [4, 4], [3, 4], [4, 3]]
  1533. >>> Z = ward(pdist(X))
  1534. >>> Z
  1535. array([[ 0. , 1. , 1. , 2. ],
  1536. [ 3. , 4. , 1. , 2. ],
  1537. [ 6. , 7. , 1. , 2. ],
  1538. [ 9. , 10. , 1. , 2. ],
  1539. [ 2. , 12. , 1.29099445, 3. ],
  1540. [ 5. , 13. , 1.29099445, 3. ],
  1541. [ 8. , 14. , 1.29099445, 3. ],
  1542. [11. , 15. , 1.29099445, 3. ],
  1543. [16. , 17. , 5.77350269, 6. ],
  1544. [18. , 19. , 5.77350269, 6. ],
  1545. [20. , 21. , 8.16496581, 12. ]])
  1546. After a linkage matrix ``Z`` has been created, we can use
  1547. `scipy.cluster.hierarchy.to_mlab_linkage` to convert it
  1548. into MATLAB format:
  1549. >>> mZ = to_mlab_linkage(Z)
  1550. >>> mZ
  1551. array([[ 1. , 2. , 1. ],
  1552. [ 4. , 5. , 1. ],
  1553. [ 7. , 8. , 1. ],
  1554. [ 10. , 11. , 1. ],
  1555. [ 3. , 13. , 1.29099445],
  1556. [ 6. , 14. , 1.29099445],
  1557. [ 9. , 15. , 1.29099445],
  1558. [ 12. , 16. , 1.29099445],
  1559. [ 17. , 18. , 5.77350269],
  1560. [ 19. , 20. , 5.77350269],
  1561. [ 21. , 22. , 8.16496581]])
  1562. The new linkage matrix ``mZ`` uses 1-indexing for all the
  1563. clusters (instead of 0-indexing). Also, the last column of
  1564. the original linkage matrix has been dropped.
  1565. """
  1566. Z = np.asarray(Z, order='c', dtype=np.double)
  1567. Zs = Z.shape
  1568. if len(Zs) == 0 or (len(Zs) == 1 and Zs[0] == 0):
  1569. return Z.copy()
  1570. is_valid_linkage(Z, throw=True, name='Z')
  1571. ZP = Z[:, 0:3].copy()
  1572. ZP[:, 0:2] += 1.0
  1573. return ZP
  1574. def is_monotonic(Z):
  1575. """
  1576. Return True if the linkage passed is monotonic.
  1577. The linkage is monotonic if for every cluster :math:`s` and :math:`t`
  1578. joined, the distance between them is no less than the distance
  1579. between any previously joined clusters.
  1580. Parameters
  1581. ----------
  1582. Z : ndarray
  1583. The linkage matrix to check for monotonicity.
  1584. Returns
  1585. -------
  1586. b : bool
  1587. A boolean indicating whether the linkage is monotonic.
  1588. See Also
  1589. --------
  1590. linkage : for a description of what a linkage matrix is.
  1591. Examples
  1592. --------
  1593. >>> from scipy.cluster.hierarchy import median, ward, is_monotonic
  1594. >>> from scipy.spatial.distance import pdist
  1595. By definition, some hierarchical clustering algorithms - such as
  1596. `scipy.cluster.hierarchy.ward` - produce monotonic assignments of
  1597. samples to clusters; however, this is not always true for other
  1598. hierarchical methods - e.g. `scipy.cluster.hierarchy.median`.
  1599. Given a linkage matrix ``Z`` (as the result of a hierarchical clustering
  1600. method) we can test programmatically whether it has the monotonicity
  1601. property or not, using `scipy.cluster.hierarchy.is_monotonic`:
  1602. >>> X = [[0, 0], [0, 1], [1, 0],
  1603. ... [0, 4], [0, 3], [1, 4],
  1604. ... [4, 0], [3, 0], [4, 1],
  1605. ... [4, 4], [3, 4], [4, 3]]
  1606. >>> Z = ward(pdist(X))
  1607. >>> Z
  1608. array([[ 0. , 1. , 1. , 2. ],
  1609. [ 3. , 4. , 1. , 2. ],
  1610. [ 6. , 7. , 1. , 2. ],
  1611. [ 9. , 10. , 1. , 2. ],
  1612. [ 2. , 12. , 1.29099445, 3. ],
  1613. [ 5. , 13. , 1.29099445, 3. ],
  1614. [ 8. , 14. , 1.29099445, 3. ],
  1615. [11. , 15. , 1.29099445, 3. ],
  1616. [16. , 17. , 5.77350269, 6. ],
  1617. [18. , 19. , 5.77350269, 6. ],
  1618. [20. , 21. , 8.16496581, 12. ]])
  1619. >>> is_monotonic(Z)
  1620. True
  1621. >>> Z = median(pdist(X))
  1622. >>> Z
  1623. array([[ 0. , 1. , 1. , 2. ],
  1624. [ 3. , 4. , 1. , 2. ],
  1625. [ 9. , 10. , 1. , 2. ],
  1626. [ 6. , 7. , 1. , 2. ],
  1627. [ 2. , 12. , 1.11803399, 3. ],
  1628. [ 5. , 13. , 1.11803399, 3. ],
  1629. [ 8. , 15. , 1.11803399, 3. ],
  1630. [11. , 14. , 1.11803399, 3. ],
  1631. [18. , 19. , 3. , 6. ],
  1632. [16. , 17. , 3.5 , 6. ],
  1633. [20. , 21. , 3.25 , 12. ]])
  1634. >>> is_monotonic(Z)
  1635. False
  1636. Note that this method is equivalent to just verifying that the distances
  1637. in the third column of the linkage matrix appear in a monotonically
  1638. increasing order.
  1639. """
  1640. Z = np.asarray(Z, order='c')
  1641. is_valid_linkage(Z, throw=True, name='Z')
  1642. # We expect the i'th value to be greater than its successor.
  1643. return (Z[1:, 2] >= Z[:-1, 2]).all()
  1644. def is_valid_im(R, warning=False, throw=False, name=None):
  1645. """Return True if the inconsistency matrix passed is valid.
  1646. It must be a :math:`n` by 4 array of doubles. The standard
  1647. deviations ``R[:,1]`` must be nonnegative. The link counts
  1648. ``R[:,2]`` must be positive and no greater than :math:`n-1`.
  1649. Parameters
  1650. ----------
  1651. R : ndarray
  1652. The inconsistency matrix to check for validity.
  1653. warning : bool, optional
  1654. When True, issues a Python warning if the linkage
  1655. matrix passed is invalid.
  1656. throw : bool, optional
  1657. When True, throws a Python exception if the linkage
  1658. matrix passed is invalid.
  1659. name : str, optional
  1660. This string refers to the variable name of the invalid
  1661. linkage matrix.
  1662. Returns
  1663. -------
  1664. b : bool
  1665. True if the inconsistency matrix is valid.
  1666. See Also
  1667. --------
  1668. linkage : for a description of what a linkage matrix is.
  1669. inconsistent : for the creation of a inconsistency matrix.
  1670. Examples
  1671. --------
  1672. >>> from scipy.cluster.hierarchy import ward, inconsistent, is_valid_im
  1673. >>> from scipy.spatial.distance import pdist
  1674. Given a data set ``X``, we can apply a clustering method to obtain a
  1675. linkage matrix ``Z``. `scipy.cluster.hierarchy.inconsistent` can
  1676. be also used to obtain the inconsistency matrix ``R`` associated to
  1677. this clustering process:
  1678. >>> X = [[0, 0], [0, 1], [1, 0],
  1679. ... [0, 4], [0, 3], [1, 4],
  1680. ... [4, 0], [3, 0], [4, 1],
  1681. ... [4, 4], [3, 4], [4, 3]]
  1682. >>> Z = ward(pdist(X))
  1683. >>> R = inconsistent(Z)
  1684. >>> Z
  1685. array([[ 0. , 1. , 1. , 2. ],
  1686. [ 3. , 4. , 1. , 2. ],
  1687. [ 6. , 7. , 1. , 2. ],
  1688. [ 9. , 10. , 1. , 2. ],
  1689. [ 2. , 12. , 1.29099445, 3. ],
  1690. [ 5. , 13. , 1.29099445, 3. ],
  1691. [ 8. , 14. , 1.29099445, 3. ],
  1692. [11. , 15. , 1.29099445, 3. ],
  1693. [16. , 17. , 5.77350269, 6. ],
  1694. [18. , 19. , 5.77350269, 6. ],
  1695. [20. , 21. , 8.16496581, 12. ]])
  1696. >>> R
  1697. array([[1. , 0. , 1. , 0. ],
  1698. [1. , 0. , 1. , 0. ],
  1699. [1. , 0. , 1. , 0. ],
  1700. [1. , 0. , 1. , 0. ],
  1701. [1.14549722, 0.20576415, 2. , 0.70710678],
  1702. [1.14549722, 0.20576415, 2. , 0.70710678],
  1703. [1.14549722, 0.20576415, 2. , 0.70710678],
  1704. [1.14549722, 0.20576415, 2. , 0.70710678],
  1705. [2.78516386, 2.58797734, 3. , 1.15470054],
  1706. [2.78516386, 2.58797734, 3. , 1.15470054],
  1707. [6.57065706, 1.38071187, 3. , 1.15470054]])
  1708. Now we can use `scipy.cluster.hierarchy.is_valid_im` to verify that
  1709. ``R`` is correct:
  1710. >>> is_valid_im(R)
  1711. True
  1712. However, if ``R`` is wrongly constructed (e.g., one of the standard
  1713. deviations is set to a negative value), then the check will fail:
  1714. >>> R[-1,1] = R[-1,1] * -1
  1715. >>> is_valid_im(R)
  1716. False
  1717. """
  1718. R = np.asarray(R, order='c')
  1719. valid = True
  1720. name_str = "%r " % name if name else ''
  1721. try:
  1722. if type(R) != np.ndarray:
  1723. raise TypeError('Variable %spassed as inconsistency matrix is not '
  1724. 'a numpy array.' % name_str)
  1725. if R.dtype != np.double:
  1726. raise TypeError('Inconsistency matrix %smust contain doubles '
  1727. '(double).' % name_str)
  1728. if len(R.shape) != 2:
  1729. raise ValueError('Inconsistency matrix %smust have shape=2 (i.e. '
  1730. 'be two-dimensional).' % name_str)
  1731. if R.shape[1] != 4:
  1732. raise ValueError('Inconsistency matrix %smust have 4 columns.' %
  1733. name_str)
  1734. if R.shape[0] < 1:
  1735. raise ValueError('Inconsistency matrix %smust have at least one '
  1736. 'row.' % name_str)
  1737. if (R[:, 0] < 0).any():
  1738. raise ValueError('Inconsistency matrix %scontains negative link '
  1739. 'height means.' % name_str)
  1740. if (R[:, 1] < 0).any():
  1741. raise ValueError('Inconsistency matrix %scontains negative link '
  1742. 'height standard deviations.' % name_str)
  1743. if (R[:, 2] < 0).any():
  1744. raise ValueError('Inconsistency matrix %scontains negative link '
  1745. 'counts.' % name_str)
  1746. except Exception as e:
  1747. if throw:
  1748. raise
  1749. if warning:
  1750. _warning(str(e))
  1751. valid = False
  1752. return valid
  1753. def is_valid_linkage(Z, warning=False, throw=False, name=None):
  1754. """
  1755. Check the validity of a linkage matrix.
  1756. A linkage matrix is valid if it is a 2-D array (type double)
  1757. with :math:`n` rows and 4 columns. The first two columns must contain
  1758. indices between 0 and :math:`2n-1`. For a given row ``i``, the following
  1759. two expressions have to hold:
  1760. .. math::
  1761. 0 \\leq \\mathtt{Z[i,0]} \\leq i+n-1
  1762. 0 \\leq Z[i,1] \\leq i+n-1
  1763. I.e., a cluster cannot join another cluster unless the cluster being joined
  1764. has been generated.
  1765. Parameters
  1766. ----------
  1767. Z : array_like
  1768. Linkage matrix.
  1769. warning : bool, optional
  1770. When True, issues a Python warning if the linkage
  1771. matrix passed is invalid.
  1772. throw : bool, optional
  1773. When True, throws a Python exception if the linkage
  1774. matrix passed is invalid.
  1775. name : str, optional
  1776. This string refers to the variable name of the invalid
  1777. linkage matrix.
  1778. Returns
  1779. -------
  1780. b : bool
  1781. True if the inconsistency matrix is valid.
  1782. See Also
  1783. --------
  1784. linkage: for a description of what a linkage matrix is.
  1785. Examples
  1786. --------
  1787. >>> from scipy.cluster.hierarchy import ward, is_valid_linkage
  1788. >>> from scipy.spatial.distance import pdist
  1789. All linkage matrices generated by the clustering methods in this module
  1790. will be valid (i.e., they will have the appropriate dimensions and the two
  1791. required expressions will hold for all the rows).
  1792. We can check this using `scipy.cluster.hierarchy.is_valid_linkage`:
  1793. >>> X = [[0, 0], [0, 1], [1, 0],
  1794. ... [0, 4], [0, 3], [1, 4],
  1795. ... [4, 0], [3, 0], [4, 1],
  1796. ... [4, 4], [3, 4], [4, 3]]
  1797. >>> Z = ward(pdist(X))
  1798. >>> Z
  1799. array([[ 0. , 1. , 1. , 2. ],
  1800. [ 3. , 4. , 1. , 2. ],
  1801. [ 6. , 7. , 1. , 2. ],
  1802. [ 9. , 10. , 1. , 2. ],
  1803. [ 2. , 12. , 1.29099445, 3. ],
  1804. [ 5. , 13. , 1.29099445, 3. ],
  1805. [ 8. , 14. , 1.29099445, 3. ],
  1806. [11. , 15. , 1.29099445, 3. ],
  1807. [16. , 17. , 5.77350269, 6. ],
  1808. [18. , 19. , 5.77350269, 6. ],
  1809. [20. , 21. , 8.16496581, 12. ]])
  1810. >>> is_valid_linkage(Z)
  1811. True
  1812. However, if we create a linkage matrix in a wrong way - or if we modify
  1813. a valid one in a way that any of the required expressions don't hold
  1814. anymore, then the check will fail:
  1815. >>> Z[3][1] = 20 # the cluster number 20 is not defined at this point
  1816. >>> is_valid_linkage(Z)
  1817. False
  1818. """
  1819. Z = np.asarray(Z, order='c')
  1820. valid = True
  1821. name_str = "%r " % name if name else ''
  1822. try:
  1823. if type(Z) != np.ndarray:
  1824. raise TypeError('Passed linkage argument %sis not a valid array.' %
  1825. name_str)
  1826. if Z.dtype != np.double:
  1827. raise TypeError('Linkage matrix %smust contain doubles.' % name_str)
  1828. if len(Z.shape) != 2:
  1829. raise ValueError('Linkage matrix %smust have shape=2 (i.e. be '
  1830. 'two-dimensional).' % name_str)
  1831. if Z.shape[1] != 4:
  1832. raise ValueError('Linkage matrix %smust have 4 columns.' % name_str)
  1833. if Z.shape[0] == 0:
  1834. raise ValueError('Linkage must be computed on at least two '
  1835. 'observations.')
  1836. n = Z.shape[0]
  1837. if n > 1:
  1838. if ((Z[:, 0] < 0).any() or (Z[:, 1] < 0).any()):
  1839. raise ValueError('Linkage %scontains negative indices.' %
  1840. name_str)
  1841. if (Z[:, 2] < 0).any():
  1842. raise ValueError('Linkage %scontains negative distances.' %
  1843. name_str)
  1844. if (Z[:, 3] < 0).any():
  1845. raise ValueError('Linkage %scontains negative counts.' %
  1846. name_str)
  1847. if _check_hierarchy_uses_cluster_before_formed(Z):
  1848. raise ValueError('Linkage %suses non-singleton cluster before '
  1849. 'it is formed.' % name_str)
  1850. if _check_hierarchy_uses_cluster_more_than_once(Z):
  1851. raise ValueError('Linkage %suses the same cluster more than once.'
  1852. % name_str)
  1853. except Exception as e:
  1854. if throw:
  1855. raise
  1856. if warning:
  1857. _warning(str(e))
  1858. valid = False
  1859. return valid
  1860. def _check_hierarchy_uses_cluster_before_formed(Z):
  1861. n = Z.shape[0] + 1
  1862. for i in range(0, n - 1):
  1863. if Z[i, 0] >= n + i or Z[i, 1] >= n + i:
  1864. return True
  1865. return False
  1866. def _check_hierarchy_uses_cluster_more_than_once(Z):
  1867. n = Z.shape[0] + 1
  1868. chosen = set([])
  1869. for i in range(0, n - 1):
  1870. if (Z[i, 0] in chosen) or (Z[i, 1] in chosen) or Z[i, 0] == Z[i, 1]:
  1871. return True
  1872. chosen.add(Z[i, 0])
  1873. chosen.add(Z[i, 1])
  1874. return False
  1875. def _check_hierarchy_not_all_clusters_used(Z):
  1876. n = Z.shape[0] + 1
  1877. chosen = set([])
  1878. for i in range(0, n - 1):
  1879. chosen.add(int(Z[i, 0]))
  1880. chosen.add(int(Z[i, 1]))
  1881. must_chosen = set(range(0, 2 * n - 2))
  1882. return len(must_chosen.difference(chosen)) > 0
  1883. def num_obs_linkage(Z):
  1884. """
  1885. Return the number of original observations of the linkage matrix passed.
  1886. Parameters
  1887. ----------
  1888. Z : ndarray
  1889. The linkage matrix on which to perform the operation.
  1890. Returns
  1891. -------
  1892. n : int
  1893. The number of original observations in the linkage.
  1894. Examples
  1895. --------
  1896. >>> from scipy.cluster.hierarchy import ward, num_obs_linkage
  1897. >>> from scipy.spatial.distance import pdist
  1898. >>> X = [[0, 0], [0, 1], [1, 0],
  1899. ... [0, 4], [0, 3], [1, 4],
  1900. ... [4, 0], [3, 0], [4, 1],
  1901. ... [4, 4], [3, 4], [4, 3]]
  1902. >>> Z = ward(pdist(X))
  1903. ``Z`` is a linkage matrix obtained after using the Ward clustering method
  1904. with ``X``, a dataset with 12 data points.
  1905. >>> num_obs_linkage(Z)
  1906. 12
  1907. """
  1908. Z = np.asarray(Z, order='c')
  1909. is_valid_linkage(Z, throw=True, name='Z')
  1910. return (Z.shape[0] + 1)
  1911. def correspond(Z, Y):
  1912. """
  1913. Check for correspondence between linkage and condensed distance matrices.
  1914. They must have the same number of original observations for
  1915. the check to succeed.
  1916. This function is useful as a sanity check in algorithms that make
  1917. extensive use of linkage and distance matrices that must
  1918. correspond to the same set of original observations.
  1919. Parameters
  1920. ----------
  1921. Z : array_like
  1922. The linkage matrix to check for correspondence.
  1923. Y : array_like
  1924. The condensed distance matrix to check for correspondence.
  1925. Returns
  1926. -------
  1927. b : bool
  1928. A boolean indicating whether the linkage matrix and distance
  1929. matrix could possibly correspond to one another.
  1930. See Also
  1931. --------
  1932. linkage : for a description of what a linkage matrix is.
  1933. Examples
  1934. --------
  1935. >>> from scipy.cluster.hierarchy import ward, correspond
  1936. >>> from scipy.spatial.distance import pdist
  1937. This method can be used to check if a given linkage matrix ``Z`` has been
  1938. obtained from the application of a cluster method over a dataset ``X``:
  1939. >>> X = [[0, 0], [0, 1], [1, 0],
  1940. ... [0, 4], [0, 3], [1, 4],
  1941. ... [4, 0], [3, 0], [4, 1],
  1942. ... [4, 4], [3, 4], [4, 3]]
  1943. >>> X_condensed = pdist(X)
  1944. >>> Z = ward(X_condensed)
  1945. Here, we can compare ``Z`` and ``X`` (in condensed form):
  1946. >>> correspond(Z, X_condensed)
  1947. True
  1948. """
  1949. is_valid_linkage(Z, throw=True)
  1950. distance.is_valid_y(Y, throw=True)
  1951. Z = np.asarray(Z, order='c')
  1952. Y = np.asarray(Y, order='c')
  1953. return distance.num_obs_y(Y) == num_obs_linkage(Z)
  1954. def fcluster(Z, t, criterion='inconsistent', depth=2, R=None, monocrit=None):
  1955. """
  1956. Form flat clusters from the hierarchical clustering defined by
  1957. the given linkage matrix.
  1958. Parameters
  1959. ----------
  1960. Z : ndarray
  1961. The hierarchical clustering encoded with the matrix returned
  1962. by the `linkage` function.
  1963. t : scalar
  1964. For criteria 'inconsistent', 'distance' or 'monocrit',
  1965. this is the threshold to apply when forming flat clusters.
  1966. For 'maxclust' or 'maxclust_monocrit' criteria,
  1967. this would be max number of clusters requested.
  1968. criterion : str, optional
  1969. The criterion to use in forming flat clusters. This can
  1970. be any of the following values:
  1971. ``inconsistent`` :
  1972. If a cluster node and all its
  1973. descendants have an inconsistent value less than or equal
  1974. to `t`, then all its leaf descendants belong to the
  1975. same flat cluster. When no non-singleton cluster meets
  1976. this criterion, every node is assigned to its own
  1977. cluster. (Default)
  1978. ``distance`` :
  1979. Forms flat clusters so that the original
  1980. observations in each flat cluster have no greater a
  1981. cophenetic distance than `t`.
  1982. ``maxclust`` :
  1983. Finds a minimum threshold ``r`` so that
  1984. the cophenetic distance between any two original
  1985. observations in the same flat cluster is no more than
  1986. ``r`` and no more than `t` flat clusters are formed.
  1987. ``monocrit`` :
  1988. Forms a flat cluster from a cluster node c
  1989. with index i when ``monocrit[j] <= t``.
  1990. For example, to threshold on the maximum mean distance
  1991. as computed in the inconsistency matrix R with a
  1992. threshold of 0.8 do::
  1993. MR = maxRstat(Z, R, 3)
  1994. fcluster(Z, t=0.8, criterion='monocrit', monocrit=MR)
  1995. ``maxclust_monocrit`` :
  1996. Forms a flat cluster from a
  1997. non-singleton cluster node ``c`` when ``monocrit[i] <=
  1998. r`` for all cluster indices ``i`` below and including
  1999. ``c``. ``r`` is minimized such that no more than ``t``
  2000. flat clusters are formed. monocrit must be
  2001. monotonic. For example, to minimize the threshold t on
  2002. maximum inconsistency values so that no more than 3 flat
  2003. clusters are formed, do::
  2004. MI = maxinconsts(Z, R)
  2005. fcluster(Z, t=3, criterion='maxclust_monocrit', monocrit=MI)
  2006. depth : int, optional
  2007. The maximum depth to perform the inconsistency calculation.
  2008. It has no meaning for the other criteria. Default is 2.
  2009. R : ndarray, optional
  2010. The inconsistency matrix to use for the 'inconsistent'
  2011. criterion. This matrix is computed if not provided.
  2012. monocrit : ndarray, optional
  2013. An array of length n-1. `monocrit[i]` is the
  2014. statistics upon which non-singleton i is thresholded. The
  2015. monocrit vector must be monotonic, i.e., given a node c with
  2016. index i, for all node indices j corresponding to nodes
  2017. below c, ``monocrit[i] >= monocrit[j]``.
  2018. Returns
  2019. -------
  2020. fcluster : ndarray
  2021. An array of length ``n``. ``T[i]`` is the flat cluster number to
  2022. which original observation ``i`` belongs.
  2023. See Also
  2024. --------
  2025. linkage : for information about hierarchical clustering methods work.
  2026. Examples
  2027. --------
  2028. >>> from scipy.cluster.hierarchy import ward, fcluster
  2029. >>> from scipy.spatial.distance import pdist
  2030. All cluster linkage methods - e.g., `scipy.cluster.hierarchy.ward`
  2031. generate a linkage matrix ``Z`` as their output:
  2032. >>> X = [[0, 0], [0, 1], [1, 0],
  2033. ... [0, 4], [0, 3], [1, 4],
  2034. ... [4, 0], [3, 0], [4, 1],
  2035. ... [4, 4], [3, 4], [4, 3]]
  2036. >>> Z = ward(pdist(X))
  2037. >>> Z
  2038. array([[ 0. , 1. , 1. , 2. ],
  2039. [ 3. , 4. , 1. , 2. ],
  2040. [ 6. , 7. , 1. , 2. ],
  2041. [ 9. , 10. , 1. , 2. ],
  2042. [ 2. , 12. , 1.29099445, 3. ],
  2043. [ 5. , 13. , 1.29099445, 3. ],
  2044. [ 8. , 14. , 1.29099445, 3. ],
  2045. [11. , 15. , 1.29099445, 3. ],
  2046. [16. , 17. , 5.77350269, 6. ],
  2047. [18. , 19. , 5.77350269, 6. ],
  2048. [20. , 21. , 8.16496581, 12. ]])
  2049. This matrix represents a dendrogram, where the first and second elements
  2050. are the two clusters merged at each step, the third element is the
  2051. distance between these clusters, and the fourth element is the size of
  2052. the new cluster - the number of original data points included.
  2053. `scipy.cluster.hierarchy.fcluster` can be used to flatten the
  2054. dendrogram, obtaining as a result an assignation of the original data
  2055. points to single clusters.
  2056. This assignation mostly depends on a distance threshold ``t`` - the maximum
  2057. inter-cluster distance allowed:
  2058. >>> fcluster(Z, t=0.9, criterion='distance')
  2059. array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype=int32)
  2060. >>> fcluster(Z, t=1.1, criterion='distance')
  2061. array([1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8], dtype=int32)
  2062. >>> fcluster(Z, t=3, criterion='distance')
  2063. array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=int32)
  2064. >>> fcluster(Z, t=9, criterion='distance')
  2065. array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
  2066. In the first case, the threshold ``t`` is too small to allow any two
  2067. samples in the data to form a cluster, so 12 different clusters are
  2068. returned.
  2069. In the second case, the threshold is large enough to allow the first
  2070. 4 points to be merged with their nearest neighbors. So, here, only 8
  2071. clusters are returned.
  2072. The third case, with a much higher threshold, allows for up to 8 data
  2073. points to be connected - so 4 clusters are returned here.
  2074. Lastly, the threshold of the fourth case is large enough to allow for
  2075. all data points to be merged together - so a single cluster is returned.
  2076. """
  2077. Z = np.asarray(Z, order='c')
  2078. is_valid_linkage(Z, throw=True, name='Z')
  2079. n = Z.shape[0] + 1
  2080. T = np.zeros((n,), dtype='i')
  2081. # Since the C code does not support striding using strides.
  2082. # The dimensions are used instead.
  2083. [Z] = _copy_arrays_if_base_present([Z])
  2084. if criterion == 'inconsistent':
  2085. if R is None:
  2086. R = inconsistent(Z, depth)
  2087. else:
  2088. R = np.asarray(R, order='c')
  2089. is_valid_im(R, throw=True, name='R')
  2090. # Since the C code does not support striding using strides.
  2091. # The dimensions are used instead.
  2092. [R] = _copy_arrays_if_base_present([R])
  2093. _hierarchy.cluster_in(Z, R, T, float(t), int(n))
  2094. elif criterion == 'distance':
  2095. _hierarchy.cluster_dist(Z, T, float(t), int(n))
  2096. elif criterion == 'maxclust':
  2097. _hierarchy.cluster_maxclust_dist(Z, T, int(n), int(t))
  2098. elif criterion == 'monocrit':
  2099. [monocrit] = _copy_arrays_if_base_present([monocrit])
  2100. _hierarchy.cluster_monocrit(Z, monocrit, T, float(t), int(n))
  2101. elif criterion == 'maxclust_monocrit':
  2102. [monocrit] = _copy_arrays_if_base_present([monocrit])
  2103. _hierarchy.cluster_maxclust_monocrit(Z, monocrit, T, int(n), int(t))
  2104. else:
  2105. raise ValueError('Invalid cluster formation criterion: %s'
  2106. % str(criterion))
  2107. return T
  2108. def fclusterdata(X, t, criterion='inconsistent',
  2109. metric='euclidean', depth=2, method='single', R=None):
  2110. """
  2111. Cluster observation data using a given metric.
  2112. Clusters the original observations in the n-by-m data
  2113. matrix X (n observations in m dimensions), using the euclidean
  2114. distance metric to calculate distances between original observations,
  2115. performs hierarchical clustering using the single linkage algorithm,
  2116. and forms flat clusters using the inconsistency method with `t` as the
  2117. cut-off threshold.
  2118. A 1-D array ``T`` of length ``n`` is returned. ``T[i]`` is
  2119. the index of the flat cluster to which the original observation ``i``
  2120. belongs.
  2121. Parameters
  2122. ----------
  2123. X : (N, M) ndarray
  2124. N by M data matrix with N observations in M dimensions.
  2125. t : scalar
  2126. For criteria 'inconsistent', 'distance' or 'monocrit',
  2127. this is the threshold to apply when forming flat clusters.
  2128. For 'maxclust' or 'maxclust_monocrit' criteria,
  2129. this would be max number of clusters requested.
  2130. criterion : str, optional
  2131. Specifies the criterion for forming flat clusters. Valid
  2132. values are 'inconsistent' (default), 'distance', or 'maxclust'
  2133. cluster formation algorithms. See `fcluster` for descriptions.
  2134. metric : str or function, optional
  2135. The distance metric for calculating pairwise distances. See
  2136. ``distance.pdist`` for descriptions and linkage to verify
  2137. compatibility with the linkage method.
  2138. depth : int, optional
  2139. The maximum depth for the inconsistency calculation. See
  2140. `inconsistent` for more information.
  2141. method : str, optional
  2142. The linkage method to use (single, complete, average,
  2143. weighted, median centroid, ward). See `linkage` for more
  2144. information. Default is "single".
  2145. R : ndarray, optional
  2146. The inconsistency matrix. It will be computed if necessary
  2147. if it is not passed.
  2148. Returns
  2149. -------
  2150. fclusterdata : ndarray
  2151. A vector of length n. T[i] is the flat cluster number to
  2152. which original observation i belongs.
  2153. See Also
  2154. --------
  2155. scipy.spatial.distance.pdist : pairwise distance metrics
  2156. Notes
  2157. -----
  2158. This function is similar to the MATLAB function ``clusterdata``.
  2159. Examples
  2160. --------
  2161. >>> from scipy.cluster.hierarchy import fclusterdata
  2162. This is a convenience method that abstracts all the steps to perform in a
  2163. typical SciPy's hierarchical clustering workflow.
  2164. * Transform the input data into a condensed matrix with `scipy.spatial.distance.pdist`.
  2165. * Apply a clustering method.
  2166. * Obtain flat clusters at a user defined distance threshold ``t`` using `scipy.cluster.hierarchy.fcluster`.
  2167. >>> X = [[0, 0], [0, 1], [1, 0],
  2168. ... [0, 4], [0, 3], [1, 4],
  2169. ... [4, 0], [3, 0], [4, 1],
  2170. ... [4, 4], [3, 4], [4, 3]]
  2171. >>> fclusterdata(X, t=1)
  2172. array([3, 3, 3, 4, 4, 4, 2, 2, 2, 1, 1, 1], dtype=int32)
  2173. The output here (for the dataset ``X``, distance threshold ``t``, and the
  2174. default settings) is four clusters with three data points each.
  2175. """
  2176. X = np.asarray(X, order='c', dtype=np.double)
  2177. if type(X) != np.ndarray or len(X.shape) != 2:
  2178. raise TypeError('The observation matrix X must be an n by m numpy '
  2179. 'array.')
  2180. Y = distance.pdist(X, metric=metric)
  2181. Z = linkage(Y, method=method)
  2182. if R is None:
  2183. R = inconsistent(Z, d=depth)
  2184. else:
  2185. R = np.asarray(R, order='c')
  2186. T = fcluster(Z, criterion=criterion, depth=depth, R=R, t=t)
  2187. return T
  2188. def leaves_list(Z):
  2189. """
  2190. Return a list of leaf node ids.
  2191. The return corresponds to the observation vector index as it appears
  2192. in the tree from left to right. Z is a linkage matrix.
  2193. Parameters
  2194. ----------
  2195. Z : ndarray
  2196. The hierarchical clustering encoded as a matrix. `Z` is
  2197. a linkage matrix. See `linkage` for more information.
  2198. Returns
  2199. -------
  2200. leaves_list : ndarray
  2201. The list of leaf node ids.
  2202. See Also
  2203. --------
  2204. dendrogram : for information about dendrogram structure.
  2205. Examples
  2206. --------
  2207. >>> from scipy.cluster.hierarchy import ward, dendrogram, leaves_list
  2208. >>> from scipy.spatial.distance import pdist
  2209. >>> from matplotlib import pyplot as plt
  2210. >>> X = [[0, 0], [0, 1], [1, 0],
  2211. ... [0, 4], [0, 3], [1, 4],
  2212. ... [4, 0], [3, 0], [4, 1],
  2213. ... [4, 4], [3, 4], [4, 3]]
  2214. >>> Z = ward(pdist(X))
  2215. The linkage matrix ``Z`` represents a dendrogram, that is, a tree that
  2216. encodes the structure of the clustering performed.
  2217. `scipy.cluster.hierarchy.leaves_list` shows the mapping between
  2218. indices in the ``X`` dataset and leaves in the dendrogram:
  2219. >>> leaves_list(Z)
  2220. array([ 2, 0, 1, 5, 3, 4, 8, 6, 7, 11, 9, 10], dtype=int32)
  2221. >>> fig = plt.figure(figsize=(25, 10))
  2222. >>> dn = dendrogram(Z)
  2223. >>> plt.show()
  2224. """
  2225. Z = np.asarray(Z, order='c')
  2226. is_valid_linkage(Z, throw=True, name='Z')
  2227. n = Z.shape[0] + 1
  2228. ML = np.zeros((n,), dtype='i')
  2229. [Z] = _copy_arrays_if_base_present([Z])
  2230. _hierarchy.prelist(Z, ML, int(n))
  2231. return ML
  2232. # Maps number of leaves to text size.
  2233. #
  2234. # p <= 20, size="12"
  2235. # 20 < p <= 30, size="10"
  2236. # 30 < p <= 50, size="8"
  2237. # 50 < p <= np.inf, size="6"
  2238. _dtextsizes = {20: 12, 30: 10, 50: 8, 85: 6, np.inf: 5}
  2239. _drotation = {20: 0, 40: 45, np.inf: 90}
  2240. _dtextsortedkeys = list(_dtextsizes.keys())
  2241. _dtextsortedkeys.sort()
  2242. _drotationsortedkeys = list(_drotation.keys())
  2243. _drotationsortedkeys.sort()
  2244. def _remove_dups(L):
  2245. """
  2246. Remove duplicates AND preserve the original order of the elements.
  2247. The set class is not guaranteed to do this.
  2248. """
  2249. seen_before = set([])
  2250. L2 = []
  2251. for i in L:
  2252. if i not in seen_before:
  2253. seen_before.add(i)
  2254. L2.append(i)
  2255. return L2
  2256. def _get_tick_text_size(p):
  2257. for k in _dtextsortedkeys:
  2258. if p <= k:
  2259. return _dtextsizes[k]
  2260. def _get_tick_rotation(p):
  2261. for k in _drotationsortedkeys:
  2262. if p <= k:
  2263. return _drotation[k]
  2264. def _plot_dendrogram(icoords, dcoords, ivl, p, n, mh, orientation,
  2265. no_labels, color_list, leaf_font_size=None,
  2266. leaf_rotation=None, contraction_marks=None,
  2267. ax=None, above_threshold_color='C0'):
  2268. # Import matplotlib here so that it's not imported unless dendrograms
  2269. # are plotted. Raise an informative error if importing fails.
  2270. try:
  2271. # if an axis is provided, don't use pylab at all
  2272. if ax is None:
  2273. import matplotlib.pylab
  2274. import matplotlib.patches
  2275. import matplotlib.collections
  2276. except ImportError as e:
  2277. raise ImportError("You must install the matplotlib library to plot "
  2278. "the dendrogram. Use no_plot=True to calculate the "
  2279. "dendrogram without plotting.") from e
  2280. if ax is None:
  2281. ax = matplotlib.pylab.gca()
  2282. # if we're using pylab, we want to trigger a draw at the end
  2283. trigger_redraw = True
  2284. else:
  2285. trigger_redraw = False
  2286. # Independent variable plot width
  2287. ivw = len(ivl) * 10
  2288. # Dependent variable plot height
  2289. dvw = mh + mh * 0.05
  2290. iv_ticks = np.arange(5, len(ivl) * 10 + 5, 10)
  2291. if orientation in ('top', 'bottom'):
  2292. if orientation == 'top':
  2293. ax.set_ylim([0, dvw])
  2294. ax.set_xlim([0, ivw])
  2295. else:
  2296. ax.set_ylim([dvw, 0])
  2297. ax.set_xlim([0, ivw])
  2298. xlines = icoords
  2299. ylines = dcoords
  2300. if no_labels:
  2301. ax.set_xticks([])
  2302. ax.set_xticklabels([])
  2303. else:
  2304. ax.set_xticks(iv_ticks)
  2305. if orientation == 'top':
  2306. ax.xaxis.set_ticks_position('bottom')
  2307. else:
  2308. ax.xaxis.set_ticks_position('top')
  2309. # Make the tick marks invisible because they cover up the links
  2310. for line in ax.get_xticklines():
  2311. line.set_visible(False)
  2312. leaf_rot = (float(_get_tick_rotation(len(ivl)))
  2313. if (leaf_rotation is None) else leaf_rotation)
  2314. leaf_font = (float(_get_tick_text_size(len(ivl)))
  2315. if (leaf_font_size is None) else leaf_font_size)
  2316. ax.set_xticklabels(ivl, rotation=leaf_rot, size=leaf_font)
  2317. elif orientation in ('left', 'right'):
  2318. if orientation == 'left':
  2319. ax.set_xlim([dvw, 0])
  2320. ax.set_ylim([0, ivw])
  2321. else:
  2322. ax.set_xlim([0, dvw])
  2323. ax.set_ylim([0, ivw])
  2324. xlines = dcoords
  2325. ylines = icoords
  2326. if no_labels:
  2327. ax.set_yticks([])
  2328. ax.set_yticklabels([])
  2329. else:
  2330. ax.set_yticks(iv_ticks)
  2331. if orientation == 'left':
  2332. ax.yaxis.set_ticks_position('right')
  2333. else:
  2334. ax.yaxis.set_ticks_position('left')
  2335. # Make the tick marks invisible because they cover up the links
  2336. for line in ax.get_yticklines():
  2337. line.set_visible(False)
  2338. leaf_font = (float(_get_tick_text_size(len(ivl)))
  2339. if (leaf_font_size is None) else leaf_font_size)
  2340. if leaf_rotation is not None:
  2341. ax.set_yticklabels(ivl, rotation=leaf_rotation, size=leaf_font)
  2342. else:
  2343. ax.set_yticklabels(ivl, size=leaf_font)
  2344. # Let's use collections instead. This way there is a separate legend item
  2345. # for each tree grouping, rather than stupidly one for each line segment.
  2346. colors_used = _remove_dups(color_list)
  2347. color_to_lines = {}
  2348. for color in colors_used:
  2349. color_to_lines[color] = []
  2350. for (xline, yline, color) in zip(xlines, ylines, color_list):
  2351. color_to_lines[color].append(list(zip(xline, yline)))
  2352. colors_to_collections = {}
  2353. # Construct the collections.
  2354. for color in colors_used:
  2355. coll = matplotlib.collections.LineCollection(color_to_lines[color],
  2356. colors=(color,))
  2357. colors_to_collections[color] = coll
  2358. # Add all the groupings below the color threshold.
  2359. for color in colors_used:
  2360. if color != above_threshold_color:
  2361. ax.add_collection(colors_to_collections[color])
  2362. # If there's a grouping of links above the color threshold, it goes last.
  2363. if above_threshold_color in colors_to_collections:
  2364. ax.add_collection(colors_to_collections[above_threshold_color])
  2365. if contraction_marks is not None:
  2366. Ellipse = matplotlib.patches.Ellipse
  2367. for (x, y) in contraction_marks:
  2368. if orientation in ('left', 'right'):
  2369. e = Ellipse((y, x), width=dvw / 100, height=1.0)
  2370. else:
  2371. e = Ellipse((x, y), width=1.0, height=dvw / 100)
  2372. ax.add_artist(e)
  2373. e.set_clip_box(ax.bbox)
  2374. e.set_alpha(0.5)
  2375. e.set_facecolor('k')
  2376. if trigger_redraw:
  2377. matplotlib.pylab.draw_if_interactive()
  2378. # C0 is used for above threshhold color
  2379. _link_line_colors_default = ('C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9')
  2380. _link_line_colors = list(_link_line_colors_default)
  2381. def set_link_color_palette(palette):
  2382. """
  2383. Set list of matplotlib color codes for use by dendrogram.
  2384. Note that this palette is global (i.e., setting it once changes the colors
  2385. for all subsequent calls to `dendrogram`) and that it affects only the
  2386. the colors below ``color_threshold``.
  2387. Note that `dendrogram` also accepts a custom coloring function through its
  2388. ``link_color_func`` keyword, which is more flexible and non-global.
  2389. Parameters
  2390. ----------
  2391. palette : list of str or None
  2392. A list of matplotlib color codes. The order of the color codes is the
  2393. order in which the colors are cycled through when color thresholding in
  2394. the dendrogram.
  2395. If ``None``, resets the palette to its default (which are matplotlib
  2396. default colors C1 to C9).
  2397. Returns
  2398. -------
  2399. None
  2400. See Also
  2401. --------
  2402. dendrogram
  2403. Notes
  2404. -----
  2405. Ability to reset the palette with ``None`` added in SciPy 0.17.0.
  2406. Examples
  2407. --------
  2408. >>> import numpy as np
  2409. >>> from scipy.cluster import hierarchy
  2410. >>> ytdist = np.array([662., 877., 255., 412., 996., 295., 468., 268.,
  2411. ... 400., 754., 564., 138., 219., 869., 669.])
  2412. >>> Z = hierarchy.linkage(ytdist, 'single')
  2413. >>> dn = hierarchy.dendrogram(Z, no_plot=True)
  2414. >>> dn['color_list']
  2415. ['C1', 'C0', 'C0', 'C0', 'C0']
  2416. >>> hierarchy.set_link_color_palette(['c', 'm', 'y', 'k'])
  2417. >>> dn = hierarchy.dendrogram(Z, no_plot=True, above_threshold_color='b')
  2418. >>> dn['color_list']
  2419. ['c', 'b', 'b', 'b', 'b']
  2420. >>> dn = hierarchy.dendrogram(Z, no_plot=True, color_threshold=267,
  2421. ... above_threshold_color='k')
  2422. >>> dn['color_list']
  2423. ['c', 'm', 'm', 'k', 'k']
  2424. Now, reset the color palette to its default:
  2425. >>> hierarchy.set_link_color_palette(None)
  2426. """
  2427. if palette is None:
  2428. # reset to its default
  2429. palette = _link_line_colors_default
  2430. elif type(palette) not in (list, tuple):
  2431. raise TypeError("palette must be a list or tuple")
  2432. _ptypes = [isinstance(p, str) for p in palette]
  2433. if False in _ptypes:
  2434. raise TypeError("all palette list elements must be color strings")
  2435. global _link_line_colors
  2436. _link_line_colors = palette
  2437. def dendrogram(Z, p=30, truncate_mode=None, color_threshold=None,
  2438. get_leaves=True, orientation='top', labels=None,
  2439. count_sort=False, distance_sort=False, show_leaf_counts=True,
  2440. no_plot=False, no_labels=False, leaf_font_size=None,
  2441. leaf_rotation=None, leaf_label_func=None,
  2442. show_contracted=False, link_color_func=None, ax=None,
  2443. above_threshold_color='C0'):
  2444. """
  2445. Plot the hierarchical clustering as a dendrogram.
  2446. The dendrogram illustrates how each cluster is
  2447. composed by drawing a U-shaped link between a non-singleton
  2448. cluster and its children. The top of the U-link indicates a
  2449. cluster merge. The two legs of the U-link indicate which clusters
  2450. were merged. The length of the two legs of the U-link represents
  2451. the distance between the child clusters. It is also the
  2452. cophenetic distance between original observations in the two
  2453. children clusters.
  2454. Parameters
  2455. ----------
  2456. Z : ndarray
  2457. The linkage matrix encoding the hierarchical clustering to
  2458. render as a dendrogram. See the ``linkage`` function for more
  2459. information on the format of ``Z``.
  2460. p : int, optional
  2461. The ``p`` parameter for ``truncate_mode``.
  2462. truncate_mode : str, optional
  2463. The dendrogram can be hard to read when the original
  2464. observation matrix from which the linkage is derived is
  2465. large. Truncation is used to condense the dendrogram. There
  2466. are several modes:
  2467. ``None``
  2468. No truncation is performed (default).
  2469. Note: ``'none'`` is an alias for ``None`` that's kept for
  2470. backward compatibility.
  2471. ``'lastp'``
  2472. The last ``p`` non-singleton clusters formed in the linkage are the
  2473. only non-leaf nodes in the linkage; they correspond to rows
  2474. ``Z[n-p-2:end]`` in ``Z``. All other non-singleton clusters are
  2475. contracted into leaf nodes.
  2476. ``'level'``
  2477. No more than ``p`` levels of the dendrogram tree are displayed.
  2478. A "level" includes all nodes with ``p`` merges from the final merge.
  2479. Note: ``'mtica'`` is an alias for ``'level'`` that's kept for
  2480. backward compatibility.
  2481. color_threshold : double, optional
  2482. For brevity, let :math:`t` be the ``color_threshold``.
  2483. Colors all the descendent links below a cluster node
  2484. :math:`k` the same color if :math:`k` is the first node below
  2485. the cut threshold :math:`t`. All links connecting nodes with
  2486. distances greater than or equal to the threshold are colored
  2487. with de default matplotlib color ``'C0'``. If :math:`t` is less
  2488. than or equal to zero, all nodes are colored ``'C0'``.
  2489. If ``color_threshold`` is None or 'default',
  2490. corresponding with MATLAB(TM) behavior, the threshold is set to
  2491. ``0.7*max(Z[:,2])``.
  2492. get_leaves : bool, optional
  2493. Includes a list ``R['leaves']=H`` in the result
  2494. dictionary. For each :math:`i`, ``H[i] == j``, cluster node
  2495. ``j`` appears in position ``i`` in the left-to-right traversal
  2496. of the leaves, where :math:`j < 2n-1` and :math:`i < n`.
  2497. orientation : str, optional
  2498. The direction to plot the dendrogram, which can be any
  2499. of the following strings:
  2500. ``'top'``
  2501. Plots the root at the top, and plot descendent links going downwards.
  2502. (default).
  2503. ``'bottom'``
  2504. Plots the root at the bottom, and plot descendent links going
  2505. upwards.
  2506. ``'left'``
  2507. Plots the root at the left, and plot descendent links going right.
  2508. ``'right'``
  2509. Plots the root at the right, and plot descendent links going left.
  2510. labels : ndarray, optional
  2511. By default, ``labels`` is None so the index of the original observation
  2512. is used to label the leaf nodes. Otherwise, this is an :math:`n`-sized
  2513. sequence, with ``n == Z.shape[0] + 1``. The ``labels[i]`` value is the
  2514. text to put under the :math:`i` th leaf node only if it corresponds to
  2515. an original observation and not a non-singleton cluster.
  2516. count_sort : str or bool, optional
  2517. For each node n, the order (visually, from left-to-right) n's
  2518. two descendent links are plotted is determined by this
  2519. parameter, which can be any of the following values:
  2520. ``False``
  2521. Nothing is done.
  2522. ``'ascending'`` or ``True``
  2523. The child with the minimum number of original objects in its cluster
  2524. is plotted first.
  2525. ``'descending'``
  2526. The child with the maximum number of original objects in its cluster
  2527. is plotted first.
  2528. Note, ``distance_sort`` and ``count_sort`` cannot both be True.
  2529. distance_sort : str or bool, optional
  2530. For each node n, the order (visually, from left-to-right) n's
  2531. two descendent links are plotted is determined by this
  2532. parameter, which can be any of the following values:
  2533. ``False``
  2534. Nothing is done.
  2535. ``'ascending'`` or ``True``
  2536. The child with the minimum distance between its direct descendents is
  2537. plotted first.
  2538. ``'descending'``
  2539. The child with the maximum distance between its direct descendents is
  2540. plotted first.
  2541. Note ``distance_sort`` and ``count_sort`` cannot both be True.
  2542. show_leaf_counts : bool, optional
  2543. When True, leaf nodes representing :math:`k>1` original
  2544. observation are labeled with the number of observations they
  2545. contain in parentheses.
  2546. no_plot : bool, optional
  2547. When True, the final rendering is not performed. This is
  2548. useful if only the data structures computed for the rendering
  2549. are needed or if matplotlib is not available.
  2550. no_labels : bool, optional
  2551. When True, no labels appear next to the leaf nodes in the
  2552. rendering of the dendrogram.
  2553. leaf_rotation : double, optional
  2554. Specifies the angle (in degrees) to rotate the leaf
  2555. labels. When unspecified, the rotation is based on the number of
  2556. nodes in the dendrogram (default is 0).
  2557. leaf_font_size : int, optional
  2558. Specifies the font size (in points) of the leaf labels. When
  2559. unspecified, the size based on the number of nodes in the
  2560. dendrogram.
  2561. leaf_label_func : lambda or function, optional
  2562. When ``leaf_label_func`` is a callable function, for each
  2563. leaf with cluster index :math:`k < 2n-1`. The function
  2564. is expected to return a string with the label for the
  2565. leaf.
  2566. Indices :math:`k < n` correspond to original observations
  2567. while indices :math:`k \\geq n` correspond to non-singleton
  2568. clusters.
  2569. For example, to label singletons with their node id and
  2570. non-singletons with their id, count, and inconsistency
  2571. coefficient, simply do::
  2572. # First define the leaf label function.
  2573. def llf(id):
  2574. if id < n:
  2575. return str(id)
  2576. else:
  2577. return '[%d %d %1.2f]' % (id, count, R[n-id,3])
  2578. # The text for the leaf nodes is going to be big so force
  2579. # a rotation of 90 degrees.
  2580. dendrogram(Z, leaf_label_func=llf, leaf_rotation=90)
  2581. # leaf_label_func can also be used together with ``truncate_mode`` parameter,
  2582. # in which case you will get your leaves labeled after truncation:
  2583. dendrogram(Z, leaf_label_func=llf, leaf_rotation=90,
  2584. truncate_mode='level', p=2)
  2585. show_contracted : bool, optional
  2586. When True the heights of non-singleton nodes contracted
  2587. into a leaf node are plotted as crosses along the link
  2588. connecting that leaf node. This really is only useful when
  2589. truncation is used (see ``truncate_mode`` parameter).
  2590. link_color_func : callable, optional
  2591. If given, `link_color_function` is called with each non-singleton id
  2592. corresponding to each U-shaped link it will paint. The function is
  2593. expected to return the color to paint the link, encoded as a matplotlib
  2594. color string code. For example::
  2595. dendrogram(Z, link_color_func=lambda k: colors[k])
  2596. colors the direct links below each untruncated non-singleton node
  2597. ``k`` using ``colors[k]``.
  2598. ax : matplotlib Axes instance, optional
  2599. If None and `no_plot` is not True, the dendrogram will be plotted
  2600. on the current axes. Otherwise if `no_plot` is not True the
  2601. dendrogram will be plotted on the given ``Axes`` instance. This can be
  2602. useful if the dendrogram is part of a more complex figure.
  2603. above_threshold_color : str, optional
  2604. This matplotlib color string sets the color of the links above the
  2605. color_threshold. The default is ``'C0'``.
  2606. Returns
  2607. -------
  2608. R : dict
  2609. A dictionary of data structures computed to render the
  2610. dendrogram. Its has the following keys:
  2611. ``'color_list'``
  2612. A list of color names. The k'th element represents the color of the
  2613. k'th link.
  2614. ``'icoord'`` and ``'dcoord'``
  2615. Each of them is a list of lists. Let ``icoord = [I1, I2, ..., Ip]``
  2616. where ``Ik = [xk1, xk2, xk3, xk4]`` and ``dcoord = [D1, D2, ..., Dp]``
  2617. where ``Dk = [yk1, yk2, yk3, yk4]``, then the k'th link painted is
  2618. ``(xk1, yk1)`` - ``(xk2, yk2)`` - ``(xk3, yk3)`` - ``(xk4, yk4)``.
  2619. ``'ivl'``
  2620. A list of labels corresponding to the leaf nodes.
  2621. ``'leaves'``
  2622. For each i, ``H[i] == j``, cluster node ``j`` appears in position
  2623. ``i`` in the left-to-right traversal of the leaves, where
  2624. :math:`j < 2n-1` and :math:`i < n`. If ``j`` is less than ``n``, the
  2625. ``i``-th leaf node corresponds to an original observation.
  2626. Otherwise, it corresponds to a non-singleton cluster.
  2627. ``'leaves_color_list'``
  2628. A list of color names. The k'th element represents the color of the
  2629. k'th leaf.
  2630. See Also
  2631. --------
  2632. linkage, set_link_color_palette
  2633. Notes
  2634. -----
  2635. It is expected that the distances in ``Z[:,2]`` be monotonic, otherwise
  2636. crossings appear in the dendrogram.
  2637. Examples
  2638. --------
  2639. >>> import numpy as np
  2640. >>> from scipy.cluster import hierarchy
  2641. >>> import matplotlib.pyplot as plt
  2642. A very basic example:
  2643. >>> ytdist = np.array([662., 877., 255., 412., 996., 295., 468., 268.,
  2644. ... 400., 754., 564., 138., 219., 869., 669.])
  2645. >>> Z = hierarchy.linkage(ytdist, 'single')
  2646. >>> plt.figure()
  2647. >>> dn = hierarchy.dendrogram(Z)
  2648. Now, plot in given axes, improve the color scheme and use both vertical and
  2649. horizontal orientations:
  2650. >>> hierarchy.set_link_color_palette(['m', 'c', 'y', 'k'])
  2651. >>> fig, axes = plt.subplots(1, 2, figsize=(8, 3))
  2652. >>> dn1 = hierarchy.dendrogram(Z, ax=axes[0], above_threshold_color='y',
  2653. ... orientation='top')
  2654. >>> dn2 = hierarchy.dendrogram(Z, ax=axes[1],
  2655. ... above_threshold_color='#bcbddc',
  2656. ... orientation='right')
  2657. >>> hierarchy.set_link_color_palette(None) # reset to default after use
  2658. >>> plt.show()
  2659. """
  2660. # This feature was thought about but never implemented (still useful?):
  2661. #
  2662. # ... = dendrogram(..., leaves_order=None)
  2663. #
  2664. # Plots the leaves in the order specified by a vector of
  2665. # original observation indices. If the vector contains duplicates
  2666. # or results in a crossing, an exception will be thrown. Passing
  2667. # None orders leaf nodes based on the order they appear in the
  2668. # pre-order traversal.
  2669. Z = np.asarray(Z, order='c')
  2670. if orientation not in ["top", "left", "bottom", "right"]:
  2671. raise ValueError("orientation must be one of 'top', 'left', "
  2672. "'bottom', or 'right'")
  2673. if labels is not None and Z.shape[0] + 1 != len(labels):
  2674. raise ValueError("Dimensions of Z and labels must be consistent.")
  2675. is_valid_linkage(Z, throw=True, name='Z')
  2676. Zs = Z.shape
  2677. n = Zs[0] + 1
  2678. if type(p) in (int, float):
  2679. p = int(p)
  2680. else:
  2681. raise TypeError('The second argument must be a number')
  2682. if truncate_mode not in ('lastp', 'mtica', 'level', 'none', None):
  2683. # 'mtica' is kept working for backwards compat.
  2684. raise ValueError('Invalid truncation mode.')
  2685. if truncate_mode == 'lastp':
  2686. if p > n or p == 0:
  2687. p = n
  2688. if truncate_mode == 'mtica':
  2689. # 'mtica' is an alias
  2690. truncate_mode = 'level'
  2691. if truncate_mode == 'level':
  2692. if p <= 0:
  2693. p = np.inf
  2694. if get_leaves:
  2695. lvs = []
  2696. else:
  2697. lvs = None
  2698. icoord_list = []
  2699. dcoord_list = []
  2700. color_list = []
  2701. current_color = [0]
  2702. currently_below_threshold = [False]
  2703. ivl = [] # list of leaves
  2704. if color_threshold is None or (isinstance(color_threshold, str) and
  2705. color_threshold == 'default'):
  2706. color_threshold = max(Z[:, 2]) * 0.7
  2707. R = {'icoord': icoord_list, 'dcoord': dcoord_list, 'ivl': ivl,
  2708. 'leaves': lvs, 'color_list': color_list}
  2709. # Empty list will be filled in _dendrogram_calculate_info
  2710. contraction_marks = [] if show_contracted else None
  2711. _dendrogram_calculate_info(
  2712. Z=Z, p=p,
  2713. truncate_mode=truncate_mode,
  2714. color_threshold=color_threshold,
  2715. get_leaves=get_leaves,
  2716. orientation=orientation,
  2717. labels=labels,
  2718. count_sort=count_sort,
  2719. distance_sort=distance_sort,
  2720. show_leaf_counts=show_leaf_counts,
  2721. i=2*n - 2,
  2722. iv=0.0,
  2723. ivl=ivl,
  2724. n=n,
  2725. icoord_list=icoord_list,
  2726. dcoord_list=dcoord_list,
  2727. lvs=lvs,
  2728. current_color=current_color,
  2729. color_list=color_list,
  2730. currently_below_threshold=currently_below_threshold,
  2731. leaf_label_func=leaf_label_func,
  2732. contraction_marks=contraction_marks,
  2733. link_color_func=link_color_func,
  2734. above_threshold_color=above_threshold_color)
  2735. if not no_plot:
  2736. mh = max(Z[:, 2])
  2737. _plot_dendrogram(icoord_list, dcoord_list, ivl, p, n, mh, orientation,
  2738. no_labels, color_list,
  2739. leaf_font_size=leaf_font_size,
  2740. leaf_rotation=leaf_rotation,
  2741. contraction_marks=contraction_marks,
  2742. ax=ax,
  2743. above_threshold_color=above_threshold_color)
  2744. R["leaves_color_list"] = _get_leaves_color_list(R)
  2745. return R
  2746. def _get_leaves_color_list(R):
  2747. leaves_color_list = [None] * len(R['leaves'])
  2748. for link_x, link_y, link_color in zip(R['icoord'],
  2749. R['dcoord'],
  2750. R['color_list']):
  2751. for (xi, yi) in zip(link_x, link_y):
  2752. if yi == 0.0 and (xi % 5 == 0 and xi % 2 == 1):
  2753. # if yi is 0.0 and xi is divisible by 5 and odd,
  2754. # the point is a leaf
  2755. # xi of leaves are 5, 15, 25, 35, ... (see `iv_ticks`)
  2756. # index of leaves are 0, 1, 2, 3, ... as below
  2757. leaf_index = (int(xi) - 5) // 10
  2758. # each leaf has a same color of its link.
  2759. leaves_color_list[leaf_index] = link_color
  2760. return leaves_color_list
  2761. def _append_singleton_leaf_node(Z, p, n, level, lvs, ivl, leaf_label_func,
  2762. i, labels):
  2763. # If the leaf id structure is not None and is a list then the caller
  2764. # to dendrogram has indicated that cluster id's corresponding to the
  2765. # leaf nodes should be recorded.
  2766. if lvs is not None:
  2767. lvs.append(int(i))
  2768. # If leaf node labels are to be displayed...
  2769. if ivl is not None:
  2770. # If a leaf_label_func has been provided, the label comes from the
  2771. # string returned from the leaf_label_func, which is a function
  2772. # passed to dendrogram.
  2773. if leaf_label_func:
  2774. ivl.append(leaf_label_func(int(i)))
  2775. else:
  2776. # Otherwise, if the dendrogram caller has passed a labels list
  2777. # for the leaf nodes, use it.
  2778. if labels is not None:
  2779. ivl.append(labels[int(i - n)])
  2780. else:
  2781. # Otherwise, use the id as the label for the leaf.x
  2782. ivl.append(str(int(i)))
  2783. def _append_nonsingleton_leaf_node(Z, p, n, level, lvs, ivl, leaf_label_func,
  2784. i, labels, show_leaf_counts):
  2785. # If the leaf id structure is not None and is a list then the caller
  2786. # to dendrogram has indicated that cluster id's corresponding to the
  2787. # leaf nodes should be recorded.
  2788. if lvs is not None:
  2789. lvs.append(int(i))
  2790. if ivl is not None:
  2791. if leaf_label_func:
  2792. ivl.append(leaf_label_func(int(i)))
  2793. else:
  2794. if show_leaf_counts:
  2795. ivl.append("(" + str(int(Z[i - n, 3])) + ")")
  2796. else:
  2797. ivl.append("")
  2798. def _append_contraction_marks(Z, iv, i, n, contraction_marks):
  2799. _append_contraction_marks_sub(Z, iv, int(Z[i - n, 0]), n, contraction_marks)
  2800. _append_contraction_marks_sub(Z, iv, int(Z[i - n, 1]), n, contraction_marks)
  2801. def _append_contraction_marks_sub(Z, iv, i, n, contraction_marks):
  2802. if i >= n:
  2803. contraction_marks.append((iv, Z[i - n, 2]))
  2804. _append_contraction_marks_sub(Z, iv, int(Z[i - n, 0]), n, contraction_marks)
  2805. _append_contraction_marks_sub(Z, iv, int(Z[i - n, 1]), n, contraction_marks)
  2806. def _dendrogram_calculate_info(Z, p, truncate_mode,
  2807. color_threshold=np.inf, get_leaves=True,
  2808. orientation='top', labels=None,
  2809. count_sort=False, distance_sort=False,
  2810. show_leaf_counts=False, i=-1, iv=0.0,
  2811. ivl=[], n=0, icoord_list=[], dcoord_list=[],
  2812. lvs=None, mhr=False,
  2813. current_color=[], color_list=[],
  2814. currently_below_threshold=[],
  2815. leaf_label_func=None, level=0,
  2816. contraction_marks=None,
  2817. link_color_func=None,
  2818. above_threshold_color='C0'):
  2819. """
  2820. Calculate the endpoints of the links as well as the labels for the
  2821. the dendrogram rooted at the node with index i. iv is the independent
  2822. variable value to plot the left-most leaf node below the root node i
  2823. (if orientation='top', this would be the left-most x value where the
  2824. plotting of this root node i and its descendents should begin).
  2825. ivl is a list to store the labels of the leaf nodes. The leaf_label_func
  2826. is called whenever ivl != None, labels == None, and
  2827. leaf_label_func != None. When ivl != None and labels != None, the
  2828. labels list is used only for labeling the leaf nodes. When
  2829. ivl == None, no labels are generated for leaf nodes.
  2830. When get_leaves==True, a list of leaves is built as they are visited
  2831. in the dendrogram.
  2832. Returns a tuple with l being the independent variable coordinate that
  2833. corresponds to the midpoint of cluster to the left of cluster i if
  2834. i is non-singleton, otherwise the independent coordinate of the leaf
  2835. node if i is a leaf node.
  2836. Returns
  2837. -------
  2838. A tuple (left, w, h, md), where:
  2839. * left is the independent variable coordinate of the center of the
  2840. the U of the subtree
  2841. * w is the amount of space used for the subtree (in independent
  2842. variable units)
  2843. * h is the height of the subtree in dependent variable units
  2844. * md is the ``max(Z[*,2]``) for all nodes ``*`` below and including
  2845. the target node.
  2846. """
  2847. if n == 0:
  2848. raise ValueError("Invalid singleton cluster count n.")
  2849. if i == -1:
  2850. raise ValueError("Invalid root cluster index i.")
  2851. if truncate_mode == 'lastp':
  2852. # If the node is a leaf node but corresponds to a non-singleton
  2853. # cluster, its label is either the empty string or the number of
  2854. # original observations belonging to cluster i.
  2855. if 2*n - p > i >= n:
  2856. d = Z[i - n, 2]
  2857. _append_nonsingleton_leaf_node(Z, p, n, level, lvs, ivl,
  2858. leaf_label_func, i, labels,
  2859. show_leaf_counts)
  2860. if contraction_marks is not None:
  2861. _append_contraction_marks(Z, iv + 5.0, i, n, contraction_marks)
  2862. return (iv + 5.0, 10.0, 0.0, d)
  2863. elif i < n:
  2864. _append_singleton_leaf_node(Z, p, n, level, lvs, ivl,
  2865. leaf_label_func, i, labels)
  2866. return (iv + 5.0, 10.0, 0.0, 0.0)
  2867. elif truncate_mode == 'level':
  2868. if i > n and level > p:
  2869. d = Z[i - n, 2]
  2870. _append_nonsingleton_leaf_node(Z, p, n, level, lvs, ivl,
  2871. leaf_label_func, i, labels,
  2872. show_leaf_counts)
  2873. if contraction_marks is not None:
  2874. _append_contraction_marks(Z, iv + 5.0, i, n, contraction_marks)
  2875. return (iv + 5.0, 10.0, 0.0, d)
  2876. elif i < n:
  2877. _append_singleton_leaf_node(Z, p, n, level, lvs, ivl,
  2878. leaf_label_func, i, labels)
  2879. return (iv + 5.0, 10.0, 0.0, 0.0)
  2880. # Otherwise, only truncate if we have a leaf node.
  2881. #
  2882. # Only place leaves if they correspond to original observations.
  2883. if i < n:
  2884. _append_singleton_leaf_node(Z, p, n, level, lvs, ivl,
  2885. leaf_label_func, i, labels)
  2886. return (iv + 5.0, 10.0, 0.0, 0.0)
  2887. # !!! Otherwise, we don't have a leaf node, so work on plotting a
  2888. # non-leaf node.
  2889. # Actual indices of a and b
  2890. aa = int(Z[i - n, 0])
  2891. ab = int(Z[i - n, 1])
  2892. if aa >= n:
  2893. # The number of singletons below cluster a
  2894. na = Z[aa - n, 3]
  2895. # The distance between a's two direct children.
  2896. da = Z[aa - n, 2]
  2897. else:
  2898. na = 1
  2899. da = 0.0
  2900. if ab >= n:
  2901. nb = Z[ab - n, 3]
  2902. db = Z[ab - n, 2]
  2903. else:
  2904. nb = 1
  2905. db = 0.0
  2906. if count_sort == 'ascending' or count_sort == True:
  2907. # If a has a count greater than b, it and its descendents should
  2908. # be drawn to the right. Otherwise, to the left.
  2909. if na > nb:
  2910. # The cluster index to draw to the left (ua) will be ab
  2911. # and the one to draw to the right (ub) will be aa
  2912. ua = ab
  2913. ub = aa
  2914. else:
  2915. ua = aa
  2916. ub = ab
  2917. elif count_sort == 'descending':
  2918. # If a has a count less than or equal to b, it and its
  2919. # descendents should be drawn to the left. Otherwise, to
  2920. # the right.
  2921. if na > nb:
  2922. ua = aa
  2923. ub = ab
  2924. else:
  2925. ua = ab
  2926. ub = aa
  2927. elif distance_sort == 'ascending' or distance_sort == True:
  2928. # If a has a distance greater than b, it and its descendents should
  2929. # be drawn to the right. Otherwise, to the left.
  2930. if da > db:
  2931. ua = ab
  2932. ub = aa
  2933. else:
  2934. ua = aa
  2935. ub = ab
  2936. elif distance_sort == 'descending':
  2937. # If a has a distance less than or equal to b, it and its
  2938. # descendents should be drawn to the left. Otherwise, to
  2939. # the right.
  2940. if da > db:
  2941. ua = aa
  2942. ub = ab
  2943. else:
  2944. ua = ab
  2945. ub = aa
  2946. else:
  2947. ua = aa
  2948. ub = ab
  2949. # Updated iv variable and the amount of space used.
  2950. (uiva, uwa, uah, uamd) = \
  2951. _dendrogram_calculate_info(
  2952. Z=Z, p=p,
  2953. truncate_mode=truncate_mode,
  2954. color_threshold=color_threshold,
  2955. get_leaves=get_leaves,
  2956. orientation=orientation,
  2957. labels=labels,
  2958. count_sort=count_sort,
  2959. distance_sort=distance_sort,
  2960. show_leaf_counts=show_leaf_counts,
  2961. i=ua, iv=iv, ivl=ivl, n=n,
  2962. icoord_list=icoord_list,
  2963. dcoord_list=dcoord_list, lvs=lvs,
  2964. current_color=current_color,
  2965. color_list=color_list,
  2966. currently_below_threshold=currently_below_threshold,
  2967. leaf_label_func=leaf_label_func,
  2968. level=level + 1, contraction_marks=contraction_marks,
  2969. link_color_func=link_color_func,
  2970. above_threshold_color=above_threshold_color)
  2971. h = Z[i - n, 2]
  2972. if h >= color_threshold or color_threshold <= 0:
  2973. c = above_threshold_color
  2974. if currently_below_threshold[0]:
  2975. current_color[0] = (current_color[0] + 1) % len(_link_line_colors)
  2976. currently_below_threshold[0] = False
  2977. else:
  2978. currently_below_threshold[0] = True
  2979. c = _link_line_colors[current_color[0]]
  2980. (uivb, uwb, ubh, ubmd) = \
  2981. _dendrogram_calculate_info(
  2982. Z=Z, p=p,
  2983. truncate_mode=truncate_mode,
  2984. color_threshold=color_threshold,
  2985. get_leaves=get_leaves,
  2986. orientation=orientation,
  2987. labels=labels,
  2988. count_sort=count_sort,
  2989. distance_sort=distance_sort,
  2990. show_leaf_counts=show_leaf_counts,
  2991. i=ub, iv=iv + uwa, ivl=ivl, n=n,
  2992. icoord_list=icoord_list,
  2993. dcoord_list=dcoord_list, lvs=lvs,
  2994. current_color=current_color,
  2995. color_list=color_list,
  2996. currently_below_threshold=currently_below_threshold,
  2997. leaf_label_func=leaf_label_func,
  2998. level=level + 1, contraction_marks=contraction_marks,
  2999. link_color_func=link_color_func,
  3000. above_threshold_color=above_threshold_color)
  3001. max_dist = max(uamd, ubmd, h)
  3002. icoord_list.append([uiva, uiva, uivb, uivb])
  3003. dcoord_list.append([uah, h, h, ubh])
  3004. if link_color_func is not None:
  3005. v = link_color_func(int(i))
  3006. if not isinstance(v, str):
  3007. raise TypeError("link_color_func must return a matplotlib "
  3008. "color string!")
  3009. color_list.append(v)
  3010. else:
  3011. color_list.append(c)
  3012. return (((uiva + uivb) / 2), uwa + uwb, h, max_dist)
  3013. def is_isomorphic(T1, T2):
  3014. """
  3015. Determine if two different cluster assignments are equivalent.
  3016. Parameters
  3017. ----------
  3018. T1 : array_like
  3019. An assignment of singleton cluster ids to flat cluster ids.
  3020. T2 : array_like
  3021. An assignment of singleton cluster ids to flat cluster ids.
  3022. Returns
  3023. -------
  3024. b : bool
  3025. Whether the flat cluster assignments `T1` and `T2` are
  3026. equivalent.
  3027. See Also
  3028. --------
  3029. linkage : for a description of what a linkage matrix is.
  3030. fcluster : for the creation of flat cluster assignments.
  3031. Examples
  3032. --------
  3033. >>> from scipy.cluster.hierarchy import fcluster, is_isomorphic
  3034. >>> from scipy.cluster.hierarchy import single, complete
  3035. >>> from scipy.spatial.distance import pdist
  3036. Two flat cluster assignments can be isomorphic if they represent the same
  3037. cluster assignment, with different labels.
  3038. For example, we can use the `scipy.cluster.hierarchy.single`: method
  3039. and flatten the output to four clusters:
  3040. >>> X = [[0, 0], [0, 1], [1, 0],
  3041. ... [0, 4], [0, 3], [1, 4],
  3042. ... [4, 0], [3, 0], [4, 1],
  3043. ... [4, 4], [3, 4], [4, 3]]
  3044. >>> Z = single(pdist(X))
  3045. >>> T = fcluster(Z, 1, criterion='distance')
  3046. >>> T
  3047. array([3, 3, 3, 4, 4, 4, 2, 2, 2, 1, 1, 1], dtype=int32)
  3048. We can then do the same using the
  3049. `scipy.cluster.hierarchy.complete`: method:
  3050. >>> Z = complete(pdist(X))
  3051. >>> T_ = fcluster(Z, 1.5, criterion='distance')
  3052. >>> T_
  3053. array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=int32)
  3054. As we can see, in both cases we obtain four clusters and all the data
  3055. points are distributed in the same way - the only thing that changes
  3056. are the flat cluster labels (3 => 1, 4 =>2, 2 =>3 and 4 =>1), so both
  3057. cluster assignments are isomorphic:
  3058. >>> is_isomorphic(T, T_)
  3059. True
  3060. """
  3061. T1 = np.asarray(T1, order='c')
  3062. T2 = np.asarray(T2, order='c')
  3063. if type(T1) != np.ndarray:
  3064. raise TypeError('T1 must be a numpy array.')
  3065. if type(T2) != np.ndarray:
  3066. raise TypeError('T2 must be a numpy array.')
  3067. T1S = T1.shape
  3068. T2S = T2.shape
  3069. if len(T1S) != 1:
  3070. raise ValueError('T1 must be one-dimensional.')
  3071. if len(T2S) != 1:
  3072. raise ValueError('T2 must be one-dimensional.')
  3073. if T1S[0] != T2S[0]:
  3074. raise ValueError('T1 and T2 must have the same number of elements.')
  3075. n = T1S[0]
  3076. d1 = {}
  3077. d2 = {}
  3078. for i in range(0, n):
  3079. if T1[i] in d1:
  3080. if not T2[i] in d2:
  3081. return False
  3082. if d1[T1[i]] != T2[i] or d2[T2[i]] != T1[i]:
  3083. return False
  3084. elif T2[i] in d2:
  3085. return False
  3086. else:
  3087. d1[T1[i]] = T2[i]
  3088. d2[T2[i]] = T1[i]
  3089. return True
  3090. def maxdists(Z):
  3091. """
  3092. Return the maximum distance between any non-singleton cluster.
  3093. Parameters
  3094. ----------
  3095. Z : ndarray
  3096. The hierarchical clustering encoded as a matrix. See
  3097. ``linkage`` for more information.
  3098. Returns
  3099. -------
  3100. maxdists : ndarray
  3101. A ``(n-1)`` sized numpy array of doubles; ``MD[i]`` represents
  3102. the maximum distance between any cluster (including
  3103. singletons) below and including the node with index i. More
  3104. specifically, ``MD[i] = Z[Q(i)-n, 2].max()`` where ``Q(i)`` is the
  3105. set of all node indices below and including node i.
  3106. See Also
  3107. --------
  3108. linkage : for a description of what a linkage matrix is.
  3109. is_monotonic : for testing for monotonicity of a linkage matrix.
  3110. Examples
  3111. --------
  3112. >>> from scipy.cluster.hierarchy import median, maxdists
  3113. >>> from scipy.spatial.distance import pdist
  3114. Given a linkage matrix ``Z``, `scipy.cluster.hierarchy.maxdists`
  3115. computes for each new cluster generated (i.e., for each row of the linkage
  3116. matrix) what is the maximum distance between any two child clusters.
  3117. Due to the nature of hierarchical clustering, in many cases this is going
  3118. to be just the distance between the two child clusters that were merged
  3119. to form the current one - that is, Z[:,2].
  3120. However, for non-monotonic cluster assignments such as
  3121. `scipy.cluster.hierarchy.median` clustering this is not always the
  3122. case: There may be cluster formations were the distance between the two
  3123. clusters merged is smaller than the distance between their children.
  3124. We can see this in an example:
  3125. >>> X = [[0, 0], [0, 1], [1, 0],
  3126. ... [0, 4], [0, 3], [1, 4],
  3127. ... [4, 0], [3, 0], [4, 1],
  3128. ... [4, 4], [3, 4], [4, 3]]
  3129. >>> Z = median(pdist(X))
  3130. >>> Z
  3131. array([[ 0. , 1. , 1. , 2. ],
  3132. [ 3. , 4. , 1. , 2. ],
  3133. [ 9. , 10. , 1. , 2. ],
  3134. [ 6. , 7. , 1. , 2. ],
  3135. [ 2. , 12. , 1.11803399, 3. ],
  3136. [ 5. , 13. , 1.11803399, 3. ],
  3137. [ 8. , 15. , 1.11803399, 3. ],
  3138. [11. , 14. , 1.11803399, 3. ],
  3139. [18. , 19. , 3. , 6. ],
  3140. [16. , 17. , 3.5 , 6. ],
  3141. [20. , 21. , 3.25 , 12. ]])
  3142. >>> maxdists(Z)
  3143. array([1. , 1. , 1. , 1. , 1.11803399,
  3144. 1.11803399, 1.11803399, 1.11803399, 3. , 3.5 ,
  3145. 3.5 ])
  3146. Note that while the distance between the two clusters merged when creating the
  3147. last cluster is 3.25, there are two children (clusters 16 and 17) whose distance
  3148. is larger (3.5). Thus, `scipy.cluster.hierarchy.maxdists` returns 3.5 in
  3149. this case.
  3150. """
  3151. Z = np.asarray(Z, order='c', dtype=np.double)
  3152. is_valid_linkage(Z, throw=True, name='Z')
  3153. n = Z.shape[0] + 1
  3154. MD = np.zeros((n - 1,))
  3155. [Z] = _copy_arrays_if_base_present([Z])
  3156. _hierarchy.get_max_dist_for_each_cluster(Z, MD, int(n))
  3157. return MD
  3158. def maxinconsts(Z, R):
  3159. """
  3160. Return the maximum inconsistency coefficient for each
  3161. non-singleton cluster and its children.
  3162. Parameters
  3163. ----------
  3164. Z : ndarray
  3165. The hierarchical clustering encoded as a matrix. See
  3166. `linkage` for more information.
  3167. R : ndarray
  3168. The inconsistency matrix.
  3169. Returns
  3170. -------
  3171. MI : ndarray
  3172. A monotonic ``(n-1)``-sized numpy array of doubles.
  3173. See Also
  3174. --------
  3175. linkage : for a description of what a linkage matrix is.
  3176. inconsistent : for the creation of a inconsistency matrix.
  3177. Examples
  3178. --------
  3179. >>> from scipy.cluster.hierarchy import median, inconsistent, maxinconsts
  3180. >>> from scipy.spatial.distance import pdist
  3181. Given a data set ``X``, we can apply a clustering method to obtain a
  3182. linkage matrix ``Z``. `scipy.cluster.hierarchy.inconsistent` can
  3183. be also used to obtain the inconsistency matrix ``R`` associated to
  3184. this clustering process:
  3185. >>> X = [[0, 0], [0, 1], [1, 0],
  3186. ... [0, 4], [0, 3], [1, 4],
  3187. ... [4, 0], [3, 0], [4, 1],
  3188. ... [4, 4], [3, 4], [4, 3]]
  3189. >>> Z = median(pdist(X))
  3190. >>> R = inconsistent(Z)
  3191. >>> Z
  3192. array([[ 0. , 1. , 1. , 2. ],
  3193. [ 3. , 4. , 1. , 2. ],
  3194. [ 9. , 10. , 1. , 2. ],
  3195. [ 6. , 7. , 1. , 2. ],
  3196. [ 2. , 12. , 1.11803399, 3. ],
  3197. [ 5. , 13. , 1.11803399, 3. ],
  3198. [ 8. , 15. , 1.11803399, 3. ],
  3199. [11. , 14. , 1.11803399, 3. ],
  3200. [18. , 19. , 3. , 6. ],
  3201. [16. , 17. , 3.5 , 6. ],
  3202. [20. , 21. , 3.25 , 12. ]])
  3203. >>> R
  3204. array([[1. , 0. , 1. , 0. ],
  3205. [1. , 0. , 1. , 0. ],
  3206. [1. , 0. , 1. , 0. ],
  3207. [1. , 0. , 1. , 0. ],
  3208. [1.05901699, 0.08346263, 2. , 0.70710678],
  3209. [1.05901699, 0.08346263, 2. , 0.70710678],
  3210. [1.05901699, 0.08346263, 2. , 0.70710678],
  3211. [1.05901699, 0.08346263, 2. , 0.70710678],
  3212. [1.74535599, 1.08655358, 3. , 1.15470054],
  3213. [1.91202266, 1.37522872, 3. , 1.15470054],
  3214. [3.25 , 0.25 , 3. , 0. ]])
  3215. Here, `scipy.cluster.hierarchy.maxinconsts` can be used to compute
  3216. the maximum value of the inconsistency statistic (the last column of
  3217. ``R``) for each non-singleton cluster and its children:
  3218. >>> maxinconsts(Z, R)
  3219. array([0. , 0. , 0. , 0. , 0.70710678,
  3220. 0.70710678, 0.70710678, 0.70710678, 1.15470054, 1.15470054,
  3221. 1.15470054])
  3222. """
  3223. Z = np.asarray(Z, order='c')
  3224. R = np.asarray(R, order='c')
  3225. is_valid_linkage(Z, throw=True, name='Z')
  3226. is_valid_im(R, throw=True, name='R')
  3227. n = Z.shape[0] + 1
  3228. if Z.shape[0] != R.shape[0]:
  3229. raise ValueError("The inconsistency matrix and linkage matrix each "
  3230. "have a different number of rows.")
  3231. MI = np.zeros((n - 1,))
  3232. [Z, R] = _copy_arrays_if_base_present([Z, R])
  3233. _hierarchy.get_max_Rfield_for_each_cluster(Z, R, MI, int(n), 3)
  3234. return MI
  3235. def maxRstat(Z, R, i):
  3236. """
  3237. Return the maximum statistic for each non-singleton cluster and its
  3238. children.
  3239. Parameters
  3240. ----------
  3241. Z : array_like
  3242. The hierarchical clustering encoded as a matrix. See `linkage` for more
  3243. information.
  3244. R : array_like
  3245. The inconsistency matrix.
  3246. i : int
  3247. The column of `R` to use as the statistic.
  3248. Returns
  3249. -------
  3250. MR : ndarray
  3251. Calculates the maximum statistic for the i'th column of the
  3252. inconsistency matrix `R` for each non-singleton cluster
  3253. node. ``MR[j]`` is the maximum over ``R[Q(j)-n, i]``, where
  3254. ``Q(j)`` the set of all node ids corresponding to nodes below
  3255. and including ``j``.
  3256. See Also
  3257. --------
  3258. linkage : for a description of what a linkage matrix is.
  3259. inconsistent : for the creation of a inconsistency matrix.
  3260. Examples
  3261. --------
  3262. >>> from scipy.cluster.hierarchy import median, inconsistent, maxRstat
  3263. >>> from scipy.spatial.distance import pdist
  3264. Given a data set ``X``, we can apply a clustering method to obtain a
  3265. linkage matrix ``Z``. `scipy.cluster.hierarchy.inconsistent` can
  3266. be also used to obtain the inconsistency matrix ``R`` associated to
  3267. this clustering process:
  3268. >>> X = [[0, 0], [0, 1], [1, 0],
  3269. ... [0, 4], [0, 3], [1, 4],
  3270. ... [4, 0], [3, 0], [4, 1],
  3271. ... [4, 4], [3, 4], [4, 3]]
  3272. >>> Z = median(pdist(X))
  3273. >>> R = inconsistent(Z)
  3274. >>> R
  3275. array([[1. , 0. , 1. , 0. ],
  3276. [1. , 0. , 1. , 0. ],
  3277. [1. , 0. , 1. , 0. ],
  3278. [1. , 0. , 1. , 0. ],
  3279. [1.05901699, 0.08346263, 2. , 0.70710678],
  3280. [1.05901699, 0.08346263, 2. , 0.70710678],
  3281. [1.05901699, 0.08346263, 2. , 0.70710678],
  3282. [1.05901699, 0.08346263, 2. , 0.70710678],
  3283. [1.74535599, 1.08655358, 3. , 1.15470054],
  3284. [1.91202266, 1.37522872, 3. , 1.15470054],
  3285. [3.25 , 0.25 , 3. , 0. ]])
  3286. `scipy.cluster.hierarchy.maxRstat` can be used to compute
  3287. the maximum value of each column of ``R``, for each non-singleton
  3288. cluster and its children:
  3289. >>> maxRstat(Z, R, 0)
  3290. array([1. , 1. , 1. , 1. , 1.05901699,
  3291. 1.05901699, 1.05901699, 1.05901699, 1.74535599, 1.91202266,
  3292. 3.25 ])
  3293. >>> maxRstat(Z, R, 1)
  3294. array([0. , 0. , 0. , 0. , 0.08346263,
  3295. 0.08346263, 0.08346263, 0.08346263, 1.08655358, 1.37522872,
  3296. 1.37522872])
  3297. >>> maxRstat(Z, R, 3)
  3298. array([0. , 0. , 0. , 0. , 0.70710678,
  3299. 0.70710678, 0.70710678, 0.70710678, 1.15470054, 1.15470054,
  3300. 1.15470054])
  3301. """
  3302. Z = np.asarray(Z, order='c')
  3303. R = np.asarray(R, order='c')
  3304. is_valid_linkage(Z, throw=True, name='Z')
  3305. is_valid_im(R, throw=True, name='R')
  3306. if type(i) is not int:
  3307. raise TypeError('The third argument must be an integer.')
  3308. if i < 0 or i > 3:
  3309. raise ValueError('i must be an integer between 0 and 3 inclusive.')
  3310. if Z.shape[0] != R.shape[0]:
  3311. raise ValueError("The inconsistency matrix and linkage matrix each "
  3312. "have a different number of rows.")
  3313. n = Z.shape[0] + 1
  3314. MR = np.zeros((n - 1,))
  3315. [Z, R] = _copy_arrays_if_base_present([Z, R])
  3316. _hierarchy.get_max_Rfield_for_each_cluster(Z, R, MR, int(n), i)
  3317. return MR
  3318. def leaders(Z, T):
  3319. """
  3320. Return the root nodes in a hierarchical clustering.
  3321. Returns the root nodes in a hierarchical clustering corresponding
  3322. to a cut defined by a flat cluster assignment vector ``T``. See
  3323. the ``fcluster`` function for more information on the format of ``T``.
  3324. For each flat cluster :math:`j` of the :math:`k` flat clusters
  3325. represented in the n-sized flat cluster assignment vector ``T``,
  3326. this function finds the lowest cluster node :math:`i` in the linkage
  3327. tree Z, such that:
  3328. * leaf descendants belong only to flat cluster j
  3329. (i.e., ``T[p]==j`` for all :math:`p` in :math:`S(i)`, where
  3330. :math:`S(i)` is the set of leaf ids of descendant leaf nodes
  3331. with cluster node :math:`i`)
  3332. * there does not exist a leaf that is not a descendant with
  3333. :math:`i` that also belongs to cluster :math:`j`
  3334. (i.e., ``T[q]!=j`` for all :math:`q` not in :math:`S(i)`). If
  3335. this condition is violated, ``T`` is not a valid cluster
  3336. assignment vector, and an exception will be thrown.
  3337. Parameters
  3338. ----------
  3339. Z : ndarray
  3340. The hierarchical clustering encoded as a matrix. See
  3341. `linkage` for more information.
  3342. T : ndarray
  3343. The flat cluster assignment vector.
  3344. Returns
  3345. -------
  3346. L : ndarray
  3347. The leader linkage node id's stored as a k-element 1-D array,
  3348. where ``k`` is the number of flat clusters found in ``T``.
  3349. ``L[j]=i`` is the linkage cluster node id that is the
  3350. leader of flat cluster with id M[j]. If ``i < n``, ``i``
  3351. corresponds to an original observation, otherwise it
  3352. corresponds to a non-singleton cluster.
  3353. M : ndarray
  3354. The leader linkage node id's stored as a k-element 1-D array, where
  3355. ``k`` is the number of flat clusters found in ``T``. This allows the
  3356. set of flat cluster ids to be any arbitrary set of ``k`` integers.
  3357. For example: if ``L[3]=2`` and ``M[3]=8``, the flat cluster with
  3358. id 8's leader is linkage node 2.
  3359. See Also
  3360. --------
  3361. fcluster : for the creation of flat cluster assignments.
  3362. Examples
  3363. --------
  3364. >>> from scipy.cluster.hierarchy import ward, fcluster, leaders
  3365. >>> from scipy.spatial.distance import pdist
  3366. Given a linkage matrix ``Z`` - obtained after apply a clustering method
  3367. to a dataset ``X`` - and a flat cluster assignment array ``T``:
  3368. >>> X = [[0, 0], [0, 1], [1, 0],
  3369. ... [0, 4], [0, 3], [1, 4],
  3370. ... [4, 0], [3, 0], [4, 1],
  3371. ... [4, 4], [3, 4], [4, 3]]
  3372. >>> Z = ward(pdist(X))
  3373. >>> Z
  3374. array([[ 0. , 1. , 1. , 2. ],
  3375. [ 3. , 4. , 1. , 2. ],
  3376. [ 6. , 7. , 1. , 2. ],
  3377. [ 9. , 10. , 1. , 2. ],
  3378. [ 2. , 12. , 1.29099445, 3. ],
  3379. [ 5. , 13. , 1.29099445, 3. ],
  3380. [ 8. , 14. , 1.29099445, 3. ],
  3381. [11. , 15. , 1.29099445, 3. ],
  3382. [16. , 17. , 5.77350269, 6. ],
  3383. [18. , 19. , 5.77350269, 6. ],
  3384. [20. , 21. , 8.16496581, 12. ]])
  3385. >>> T = fcluster(Z, 3, criterion='distance')
  3386. >>> T
  3387. array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=int32)
  3388. `scipy.cluster.hierarchy.leaders` returns the indices of the nodes
  3389. in the dendrogram that are the leaders of each flat cluster:
  3390. >>> L, M = leaders(Z, T)
  3391. >>> L
  3392. array([16, 17, 18, 19], dtype=int32)
  3393. (remember that indices 0-11 point to the 12 data points in ``X``,
  3394. whereas indices 12-22 point to the 11 rows of ``Z``)
  3395. `scipy.cluster.hierarchy.leaders` also returns the indices of
  3396. the flat clusters in ``T``:
  3397. >>> M
  3398. array([1, 2, 3, 4], dtype=int32)
  3399. """
  3400. Z = np.asarray(Z, order='c')
  3401. T = np.asarray(T, order='c')
  3402. if type(T) != np.ndarray or T.dtype != 'i':
  3403. raise TypeError('T must be a one-dimensional numpy array of integers.')
  3404. is_valid_linkage(Z, throw=True, name='Z')
  3405. if len(T) != Z.shape[0] + 1:
  3406. raise ValueError('Mismatch: len(T)!=Z.shape[0] + 1.')
  3407. Cl = np.unique(T)
  3408. kk = len(Cl)
  3409. L = np.zeros((kk,), dtype='i')
  3410. M = np.zeros((kk,), dtype='i')
  3411. n = Z.shape[0] + 1
  3412. [Z, T] = _copy_arrays_if_base_present([Z, T])
  3413. s = _hierarchy.leaders(Z, T, L, M, int(kk), int(n))
  3414. if s >= 0:
  3415. raise ValueError(('T is not a valid assignment vector. Error found '
  3416. 'when examining linkage node %d (< 2n-1).') % s)
  3417. return (L, M)