2014-02-28 279 views
6

這似乎應該是一個容易的,但我無法弄清楚。我有一個熊貓數據框架,並且想用三列做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)獲取每個字符串的代表性整數。例如,

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具有D型int32,作爲np.unique可以處理最多2**31唯一的字符串。


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功能;

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() 

由於M4rtini在評論中指出,it't不明確的間距/串座標的比例應該是什麼; hash函數可能會給出意想不到的間距。

簡併統一的間距

如果你想有均勻分佈的,那麼你將不得不使用不同的轉換點。 例如,你可以使用

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

儘管這會導致每個點有即使標籤是相同的一個獨特的x位置,而X和Y點將被關聯,如果你用同樣的方法進行Y

退化均勻間隔

第三種方法是,首先獲得的xlab獨特成員(使用例如set),然後映射每個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