[PYTHON] 파이썬에서 다음 코드 예제와 같은 방사형 클러스터를 만들려면 어떻게해야합니까?
PYTHON파이썬에서 다음 코드 예제와 같은 방사형 클러스터를 만들려면 어떻게해야합니까?
나는이 정확한 계층을 만드는 방법에 대한 몇 가지 예제를 발견했다. (적어도 나는 그들이 그렇다고 생각한다.) 다음과 같은 stackoverflow.com/questions/2982929/ 위대한 일을하고 거의 내가 원하는 것을 수행한다.
[편집] Paul의 코드가 단순화 된 버전입니다. 이제 누군가가이 현재 클러스터 모양 대신 방사형 클러스터로 들어가는 것을 더 쉽게 할 수 있어야합니다.
import scipy
import pylab
import scipy.cluster.hierarchy as sch
def fix_verts(ax, orient=1):
for coll in ax.collections:
for pth in coll.get_paths():
vert = pth.vertices
vert[1:3,orient] = scipy.average(vert[1:3,orient])
# Generate random features and distance matrix.
x = scipy.rand(40)
D = scipy.zeros([40,40])
for i in range(40):
for j in range(40):
D[i,j] = abs(x[i] - x[j])
fig = pylab.figure(figsize=(8,8))
# Compute and plot the dendrogram.
ax2 = fig.add_axes([0.3,0.71,0.6,0.2])
Y = sch.linkage(D, method='single')
Z2 = sch.dendrogram(Y)
ax2.set_xticks([])
ax2.set_yticks([])
fix_verts(ax2,0)
fig.savefig('test.png')
그러나 나무와 같은 구조 대신 다음 다이어그램과 같은 방사형 클러스터가 필요합니다.
해결법
-
==============================
1.나는이 문제를 좀 더 연구했으며 이제는 링키지 출력을 (플롯 된 해킹을 해킹하기보다는) 직접 방사형 클러스터를 플로팅하기위한 새로운 함수를 만드는 것이 가장 좋은 것으로 보인다. 나는 결국 뭔가를 요리 할 수 있지만, 곧 아무것도 만들지는 못합니다.
나는이 문제를 좀 더 연구했으며 이제는 링키지 출력을 (플롯 된 해킹을 해킹하기보다는) 직접 방사형 클러스터를 플로팅하기위한 새로운 함수를 만드는 것이 가장 좋은 것으로 보인다. 나는 결국 뭔가를 요리 할 수 있지만, 곧 아무것도 만들지는 못합니다.
나는 당신의 데이터가 이런 종류의 방사형 삽입을 자연스럽게 인정한다고 가정하고 있습니다. 그걸 확인 했니? 귀하의 목적에 맞는 적절한 방법이 연계되어 있습니까?
어떤 방법 으로든 연결은 이진 트리 구조를 반환합니다. 당신의 예에서는보다 일반적인 나무가 있습니다. 트리 노드를 통합하는 방법에 대한 추가 지식이 필요합니다. 이 모든 준비가 원래 dendrogram 해킹의 아이디어를 무효화합니다.
최신 정보: 이 순진한 예제 플롯이 당신의 목적을 위해 충분히 유사할까요? 그렇다면, 나는 그것을 달성하기위한 몇 가지 간단한 코드를 게시 할 수있을 것이다.
업데이트 2 :
다음은 코드입니다.
radial_demo.py:
from numpy import r_, ones, pi, sort from numpy.random import rand from radial_grouper import tree, pre_order, post_order from radial_visualizer import simple_link from pylab import axis, figure, plot, subplot # ToDo: create proper documentation def _s(sp, t, o): subplot(sp) t.traverse(simple_link, order= o) axis('equal') def demo1(n): p= r_[2* pi* rand(1, n)- pi, ones((1, n))] t= tree(p) f= figure() _s(221, t, pre_order) _s(222, t, post_order) t= tree(p, tols= sort(2e0* rand(9))) _s(223, t, pre_order) _s(224, t, post_order) f.show() # f.savefig('test.png') # ToDO: implement more demos if __name__ == '__main__': demo1(123)
radial_grouper.py:
"""All grouping functionality is collected here.""" from collections import namedtuple from numpy import r_, arange, argsort, array, ones, pi, where from numpy import logical_and as land from radial_support import from_polar __all__= ['tree', 'pre_order', 'post_order'] Node= namedtuple('Node', 'ndx lnk') # ToDo: enhance documentation def _groub_by(p, tol, r): g, gm, gp= [], [], p- p[0] while True: if gp[-1]< 0: break ndx= where(land(0.<= gp, gp< tol))[0] if 0< len(ndx): g.append(ndx) gm.append(p[ndx].mean()) gp-= tol return g, array([gm, [r]* len(gm)]) def _leafs(p): return argsort(p[0]) def _create_leaf_nodes(ndx): nodes= [] for k in xrange(len(ndx)): nodes.append(Node(ndx[k], [])) return nodes def _link_and_create_nodes(_n, n_, cn, groups): nodes, n0= [], 0 for k in xrange(len(groups)): nodes.append(Node(n_+ n0, [cn[m] for m in groups[k]])) n0+= 1 return n_, n_+ n0, nodes def _process_level(nodes, polar, p, tol, scale, _n, n_): groups, p= _groub_by(p, tol, scale* polar[1, _n]) _n, n_, nodes= _link_and_create_nodes(_n, n_, nodes, groups) polar[:, _n: n_]= p return nodes, polar, _n, n_ def _create_tree(p, r0, scale, tols): if None is tols: tols= .3* pi/ 2** arange(5)[::-1] _n, n_= 0, p.shape[1] polar= ones((2, (len(tols)+ 2)* n_)) polar[0, :n_], polar[1, :n_]= p[0], r0 # leafs nodes= _create_leaf_nodes(_leafs(p)) nodes, polar, _n, n_= _process_level( nodes, polar, polar[0, _leafs(p)], tols[0], scale, _n, n_) # links for tol in tols[1:]: nodes, polar, _n, n_= _process_level( nodes, polar, polar[0, _n: n_], tol, scale, _n, n_) # root polar[:, n_]= [0., 0.] return Node(n_, nodes), polar[:, :n_+ 1] def _simplify(self): # ToDo: combine single linkages return self._root def _call(self, node0, node1, f, level): f(self, [node0.ndx, node1.ndx], level) def pre_order(self, node0, f, level= 0): for node1 in node0.lnk: _call(self, node0, node1, f, level) pre_order(self, node1, f, level+ 1) def post_order(self, node0, f, level= 0): for node1 in node0.lnk: post_order(self, node1, f, level+ 1) _call(self, node0, node1, f, level) class tree(object): def __init__(self, p, r0= pi, scale= .9, tols= None): self._n= p.shape[1] self._root, self._p= _create_tree(p, r0, scale, tols) def traverse(self, f, order= pre_order, cs= 'Cartesian'): self.points= self._p if cs is 'Cartesian': self.points= from_polar(self._p) order(self, self._root, f, 0) return self def simplify(self): self._root= _simplify(self) return self def is_root(self, ndx): return ndx== self._p.shape[1]- 1 def is_leaf(self, ndx): return ndx< self._n if __name__ == '__main__': # ToDO: add tests from numpy import r_, round from numpy.random import rand from pylab import plot, show def _l(t, n, l): # print round(a, 3), n, l, t.is_root(n[0]), t.is_leaf(n[1]) plot(t.points[0, n], t.points[1, n]) if 0== l: plot(t.points[0, n[0]], t.points[1, n[0]], 's') if t.is_leaf(n[1]): plot(t.points[0, n[1]], t.points[1, n[1]], 'o') n= 123 p= r_[2* pi* rand(1, n)- pi, ones((1, n))] t= tree(p).simplify().traverse(_l) # t= tree(p).traverse(_l, cs= 'Polar') show() # print # t.traverse(_l, post_order, cs= 'Polar')
radial_support.py:
"""All supporting functionality is collected here.""" from numpy import r_, arctan2, cos, sin from numpy import atleast_2d as a2d # ToDo: create proper documentation strings def _a(a0, a1): return r_[a2d(a0), a2d(a1)] def from_polar(p): """(theta, radius) to (x, y).""" return _a(cos(p[0])* p[1], sin(p[0])* p[1]) def to_polar(c): """(x, y) to (theta, radius).""" return _a(arctan2(c[1], c[0]), (c** 2).sum(0)** .5) def d_to_polar(D): """Distance matrix to (theta, radius).""" # this functionality is to adopt for more general situations # intended functionality: # - embedd distance matrix to 2D # - return that embedding in polar coordinates pass if __name__ == '__main__': from numpy import allclose from numpy.random import randn c= randn(2, 5) assert(allclose(c, from_polar(to_polar(c)))) # ToDO: implement more tests
radial_visualizer.py:
"""All visualization functionality is collected here.""" from pylab import plot # ToDo: create proper documentation def simple_link(t, ndx, level): """Simple_link is just a minimal example to demonstrate what can be achieved when it's called from _grouper.tree.traverse for each link. - t, tree instance - ndx, a pair of (from, to) indicies - level, of from, i.e. root is in level 0 """ plot(t.points[0, ndx], t.points[1, ndx]) if 0== level: plot(t.points[0, ndx[0]], t.points[1, ndx[0]], 's') if t.is_leaf(ndx[1]): plot(t.points[0, ndx[1]], t.points[1, ndx[1]], 'o') # ToDO: implement more suitable link visualizers # No doubt, this will the part to burn most of the dev. resources if __name__ == '__main__': # ToDO: implement tests pass
여기서 소스 코드를 찾을 수 있습니다. 어쨌든 마음에 들지 않게 고쳐 주시고 추후 수정 사항을 요지와 동기화하십시오.
-
==============================
2.matplotlib와 함께 networkx 패키지를 사용하여이 작업을 수행 할 수 있다고 생각합니다. networkx 갤러리에서 다음 예제를 확인하십시오.
matplotlib와 함께 networkx 패키지를 사용하여이 작업을 수행 할 수 있다고 생각합니다. networkx 갤러리에서 다음 예제를 확인하십시오.
http://networkx.lanl.gov/examples/drawing/circular_tree.html
일반적으로 networkx에는 많은 훌륭한 그래프 분석 및 플로팅 방법이 있습니다.
-
==============================
3.나는 dendrogram에서 각 "U"의 밑에 정점들을 합쳐주는 fix_verts 함수를 추가했다.
나는 dendrogram에서 각 "U"의 밑에 정점들을 합쳐주는 fix_verts 함수를 추가했다.
이 시도:
import scipy import pylab import scipy.cluster.hierarchy as sch def fix_verts(ax, orient=1): for coll in ax.collections: for pth in coll.get_paths(): vert = pth.vertices vert[1:3,orient] = scipy.average(vert[1:3,orient]) # Generate random features and distance matrix. x = scipy.rand(40) D = scipy.zeros([40,40]) for i in range(40): for j in range(40): D[i,j] = abs(x[i] - x[j]) fig = pylab.figure(figsize=(8,8)) # Compute and plot first dendrogram. ax1 = fig.add_axes([0.09,0.1,0.2,0.6]) Y = sch.linkage(D, method='centroid') Z1 = sch.dendrogram(Y, orientation='right') ax1.set_xticks([]) ax1.set_yticks([]) # Compute and plot second dendrogram. ax2 = fig.add_axes([0.3,0.71,0.6,0.2]) Y = sch.linkage(D, method='single') Z2 = sch.dendrogram(Y) ax2.set_xticks([]) ax2.set_yticks([]) # Plot distance matrix. axmatrix = fig.add_axes([0.3,0.1,0.6,0.6]) idx1 = Z1['leaves'] idx2 = Z2['leaves'] D = D[idx1,:] D = D[:,idx2] im = axmatrix.matshow(D, aspect='auto', origin='lower', cmap=pylab.cm.YlGnBu) axmatrix.set_xticks([]) fix_verts(ax1,1) fix_verts(ax2,0) fig.savefig('test.png')
결과는 다음과 같습니다.
그게 네가 한 일이되기를 바란다.
from https://stackoverflow.com/questions/5089030/how-do-i-create-a-radial-cluster-like-the-following-code-example-in-python by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 떠 다니는 '.0'을 떠내려 라. (0) | 2018.10.25 |
---|---|
[PYTHON] Python 'with'문 이해하기 (0) | 2018.10.25 |
[PYTHON] 크로스 플랫폼 키로거 (0) | 2018.10.25 |
[PYTHON] 팬더 시리즈 필터링 방법 (0) | 2018.10.25 |
[PYTHON] Django에서 여러 이미지 업로드하기 (0) | 2018.10.25 |