Python matplotlib中带字符串数组的散点图

Python matplotlib中带字符串数组的散点图,python,matplotlib,pandas,Python,Matplotlib,Pandas,这看起来应该很容易,但我想不出来。我有一个熊猫数据框,想做一个3列的三维散点图。X和Y列不是数字,它们是字符串,但我不认为这会有什么问题 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.sca

这看起来应该很容易,但我想不出来。我有一个熊猫数据框,想做一个3列的三维散点图。X和Y列不是数字,它们是字符串,但我不认为这会有什么问题

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

这不是一个简单的方法吗?谢谢。

尝试将字符转换为数字进行打印,然后再次将字符用于轴标签

使用散列

您可以使用该函数进行转换

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在评论中指出的,不清楚字符串坐标的间距/比例应该是多少;
hash
函数可能会给出意外的间隔

非退化均匀间距

如果要使点均匀分布,则必须使用不同的转换。 例如,您可以使用

X =[i for i in range(len(xlab))]
尽管这会导致每个点都有一个唯一的x位置,即使标签是相同的,并且如果对
y
使用相同的方法,x和y点会相互关联

退化均匀间距

第三种选择是首先获取
xlab
(使用例如
)的唯一成员,然后使用映射的唯一集将每个xlab映射到一个位置;e、 g

xmap = dict((sn, i)for i,sn in enumerate(set(xlab)))
X = [xmap[l] for l in xlab]
您可以使用获取每个字符串的代表性整数。比如说,

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
具有数据类型
int32
,如
np。unique
最多可以处理
2**31
唯一字符串



散射现在自动执行此操作(至少从matplotlib 2.1.0开始):


如果没有数字坐标,您将如何绘制点?我不明白你怎么会认为那不是问题。什么?在X轴和Y轴上创建与在X轴和Y轴阵列中找到的不同字符串相同数量的容器。对于X和Y中的每个箱子,在Z轴上绘制Z的值。这真的没那么难。不,没那么难,但这是一个足够难的问题,它不会自动地分散给你。听起来你知道解决方案了,你试着按照你刚才说的做了吗?好吧,我可以做一些数组操作并想出它。但我认为这是很多人每天都会遇到的事情,因此会有一种自动完成的方式。如果没有,我想没关系。也许我被python库的良好性能(matplotlib当然是一个例子)所宠坏了,使用enumerate和set\dictionary的组合应该可以很容易地为列表中的唯一字符串提供合理的坐标。Matplotlib适用于打印,而不是为打印准备数据。对坐标使用哈希值并不是一个好主意。这些数字的大小会弄乱刻度。@M4rtini:对于基于字符串的坐标,刻度应该是什么并不清楚-我看不出有一个明确的答案,而散列仍然可以给出一个可行的结果。@M4rtini-我添加了两个可选方案,都可以提供统一的刻度;一个给每个点一个新的x/y位置,而使用例如
set
允许相同的标签映射到相同的x/y位置。这正是我在问题上写最后一条评论时想到的+1您可能需要演示如何使用x和y记号各自的字符串标记它们。例如,
ax.set(xticks=range(len(xuniques)),xticklabels=xuniques,…)
@乔金顿:谢谢!这样更好。这样做,我得到ValueError:无法将字符串转换为float:'A'@Arthurim然后需要更新matplotlib。不确定需要什么版本,但它至少在2.1.0中工作。Python 2.7.12不工作。还有,你在这里展示的图形与代码不匹配?@YuanTao:python3已经发布10多年了。Python 2将在5个月后结束使用。升级。@101好吧,我刚意识到你指的是matplotlib版本。那么这个数字还不匹配吗?另外:谢谢你的建议。我已经安装了它们,但还没有完全迁移到Python 3。
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()
plt.scatter(['A', 'B', 'B', 'C'], [0, 1, 2, 1])