2014-02-28 4 views
6

이것은 쉬운 것으로 여겨지지만 그렇게 이해할 수없는 것처럼 보입니다. 팬더 데이터 프레임이 있고 3 개의 열이있는 3D 분산 형 플롯을 만들고 싶습니다. X 및 Y 열은 숫자가 아니며 문자열이지만 문제가되는 방법을 알지 못합니다.matplotlib에 문자열 배열이 포함 된 분산 형 플롯

X= myDataFrame.columnX.values #string 
Y= myDataFrame.columnY.values #string 
Z= myDataFrame.columnY.values #float 

fig = pl.figure() 
ax = fig.add_subplot(111, projection='3d') 
ax.scatter(X, Y, np.log10(Z), s=20, c='b') 
pl.show() 

쉬운 방법이 없습니까? 감사.

+2

어떻게 수치 좌표없이 포인트를 그릴 것인가? 그게 문제가되지 않는다고 생각하는 법을 나는 모르겠다. – M4rtini

+0

무엇? X 및 Y 축에서 찾을 수있는 다른 문자열로 X 및 Y 축에 많은 저장소를 만듭니다. 그리고 X와 Y의 모든 빈에 대해 Z 값을 Z 축에 플롯합니다.정말 그렇게 어렵지 않습니다. – elelias

+2

아니 그게 어렵지는 않지만, 그것은 당신에게 자동으로 흩어지기 힘들 정도로 어렵습니다. 그리고 솔루션을 알고있는 것처럼 들리 겠지만 방금 말한 것을 시도 했습니까? – M4rtini

답변

7

np.unique(..., return_inverse=True)을 사용하면 각 문자열에 대한 대표 int를 얻을 수 있습니다. np.unique가에서 가장 2**31 고유의 문자열을 처리 할 수 ​​있습니다 예를 들어,

In [117]: uniques, X = np.unique(['foo', 'baz', 'bar', 'foo', 'baz', 'bar'], return_inverse=True) 

In [118]: X 
Out[118]: array([2, 1, 0, 2, 1, 0]) 

참고 X는 DTYPE int32이 있는지 확인합니다.


import pandas as pd 
import numpy as np 
import matplotlib.pyplot as plt 
import mpl_toolkits.mplot3d.axes3d as axes3d 

N = 12 
arr = np.arange(N*2).reshape(N,2) 
words = np.array(['foo', 'bar', 'baz', 'quux', 'corge']) 
df = pd.DataFrame(words[arr % 5], columns=list('XY')) 
df['Z'] = np.linspace(1, 1000, N) 
Z = np.log10(df['Z']) 
Xuniques, X = np.unique(df['X'], return_inverse=True) 
Yuniques, Y = np.unique(df['Y'], return_inverse=True) 

fig = plt.figure() 
ax = fig.add_subplot(1, 1, 1, projection='3d') 
ax.scatter(X, Y, Z, s=20, c='b') 
ax.set(xticks=range(len(Xuniques)), xticklabels=Xuniques, 
     yticks=range(len(Yuniques)), yticklabels=Yuniques) 
plt.show() 

enter image description here

+0

x 및 y 틱에 각각의 문자열을 표시하는 것이 좋습니다. 예 : 'ax.set (xticks = range (len (xuniques)), xticklabels = xuniques, ...) 어느 쪽이든, 좋은 대답! –

+0

@ JoeKington : 고마워! 그게 훨씬 낫다. – unutbu

2

문자를 숫자로 변환하여 플로팅을 시도한 다음 문자를 다시 축 레이블로 사용하십시오. 당신은 변환을위한 hash 기능을 사용할 수 해시

를 사용

; M4rtini는 의견에서 지적했듯이

from mpl_toolkits.mplot3d import Axes3D 
xlab = myDataFrame.columnX.values 
ylab = myDataFrame.columnY.values 

X =[hash(l) for l in xlab] 
Y =[hash(l) for l in xlab] 

Z= myDataFrame.columnY.values #float 

fig = figure() 
ax = fig.add_subplot(111, projection='3d') 
ax.scatter(X, Y, np.log10(Z), s=20, c='b') 
ax.set_xticks(X) 
ax.set_xticklabels(xlab) 
ax.set_yticks(Y) 
ax.set_yticklabels(ylab) 
show() 

, it't는 간격이/문자열 좌표의 스케일링이 있어야 할 것을 명확하지; hash 함수가 예상치 못한 간격을 줄 수 있습니다.

당신이 균일하게 한 후 다른 변환을 사용하는 것이다 간격 포인트를 가지고 싶었다면 비축 균일 한 간격. 당신이 동일한 방법을 사용하는 경우 예를 들어 그 라벨이 같은 경우에도 고유의 X-위치를 가지고 각 지점을 일으킬 것입니다하지만 당신은

X =[i for i in range(len(xlab))] 

를 사용할 수 있고, x와 y 포인트는 상관 관계가 될 것이다 Y.

축퇴 일정한 간격

세 번째 대안은 제 (예컨대 set 사용)하고 매핑의 고유 세트를 사용하여 위치 각 xlab 매핑 xlab의 고유 부재를 얻을 수있다; 예 :

xmap = dict((sn, i)for i,sn in enumerate(set(xlab))) 
X = [xmap[l] for l in xlab] 
+1

좌표에 해시 값을 사용하는 것은 좋은 생각이 아닙니다. 그 수의 크기가 비늘을 망칠 것입니다. – M4rtini

+1

@ M4rtini : 문자열 기반 좌표에 대해 저울이 무엇인지 명확하게 알 수는 없습니다. 해시가 여전히 실행 가능한 결과를 제공하지만 명확한 해답은 없습니다. – jmetz

+1

@ M4rtini - 둘 다 획일적 인 스케일링을 제공하는 두 가지 대안 체계를 추가했습니다. 하나는 모든 포인트에 새로운 x/y 위치를 부여하는 반면, 예를 들면. 'set'은 동일한 라벨이 같은 x/y 위치에 매핑되도록합니다. – jmetz

0

살포가 자동으로 지금이 작업을 수행합니다

plt.scatter(['A', 'A', 'B', 'B'], [0, 1, 0, 1]) 

enter image description here

+0

* ValueError : 문자열을 부동으로 변환 할 수 없습니다. 'A'* – Arthurim

+0

@Arthurim 그러면 matplotlib를 업데이트해야합니다. 어떤 버전이 필요한지 모르지만 적어도 2.1.0에서 작동합니다. – naught101

관련 문제