Matplotlib 3D Bar chart: axis issue

删除回忆录丶 提交于 2019-12-04 14:04:48

问题


I am having issue with getting data on x,y,z axis..below is my code. Is there any issue with the way i have defined range(dx,dy.dz) for different axis.

result=[['122', '109', '2343', '220', '19'],
 ['15', '407', '37', '10', '102'],
 ['100', '100', '100', '100', '100'],
 ['113', '25', '19', '31', '112'],
 ['43', '219', '35', '33', '14'],
 ['132', '108', '256', '119', '14'],
 ['22', '48', '352', '51', '438']]

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.dates as dates

def format_date(x, pos=None):
     return dates.num2date(x).strftime('%m/%d/%Y')

fig=plt.figure()
ax1=fig.add_subplot(111,projection='3d')

xpos=[10/11/2013,10/12/2013,10/13/2013,10/14/2013,10/15/2013]
ypos=['A1','C1','G1','M1','M2','M3','P1']
zpos=result

dx=[5]
dy=[7]
dz=[7]
ax1.w_xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
ax1.bar3d(xpos,ypos,zpos,dx,dy,dz,color='#00ceaa')
plt.show()

I am getting below error:


TypeError                                 Traceback (most recent call last)
<ipython-input-45-02cd8e7ee228> in <module>()
     18 dz=[17]
     19 ax1.w_xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
---> 20 ax1.bar3d(xpos,ypos,zpos,dx,dy,dz,color='#00ceaa')
     21 plt.show()

C:\Users\Andalib\Anaconda\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py in bar3d(self, x, y, z, dx, dy, dz, color, zsort, *args, **kwargs)
   2316             maxx = max(xi + dxi, maxx)
   2317             miny = min(yi, miny)
-> 2318             maxy = max(yi + dyi, maxy)
   2319             minz = min(zi, minz)
   2320             maxz = max(zi + dzi, maxz)

TypeError: cannot concatenate 'str' and 'int' objects

回答1:


There are the following issues in your code:

  • xpos and ypos are usually a flatenned meshgrid with the positions of the base of the 3D bars
  • zpos gives the position of the base along the z axis, which is usually zero unless you want the bars looking like they are flying
  • xpos, ypos and zpos must have the same flattened shape and must all be 1-D arrays

Since you know the positions for each value you can use a np.arange() to create the positions xpos and ypos, and afterwards set the tick labels.

The example code is:

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm

result=[['122', '109', '2343', '220', '19'],
 ['15', '407', '37', '10', '102'],
 ['100', '100', '100', '100', '100'],
 ['113', '25', '19', '31', '112'],
 ['43', '219', '35', '33', '14'],
 ['132', '108', '256', '119', '14'],
 ['22', '48', '352', '51', '438']]

result = np.array(result, dtype=np.int)

fig=plt.figure(figsize=(5, 5), dpi=150)
ax1=fig.add_subplot(111, projection='3d')

xlabels = np.array(['10/11/2013', '10/12/2013', '10/13/2013',
                    '10/14/2013', '10/15/2013'])
xpos = np.arange(xlabels.shape[0])
ylabels = np.array(['A1','C1','G1','M1','M2','M3','P1'])
ypos = np.arange(ylabels.shape[0])

xposM, yposM = np.meshgrid(xpos, ypos, copy=False)

zpos=result
zpos = zpos.ravel()

dx=0.5
dy=0.5
dz=zpos

ax1.w_xaxis.set_ticks(xpos + dx/2.)
ax1.w_xaxis.set_ticklabels(xlabels)

ax1.w_yaxis.set_ticks(ypos + dy/2.)
ax1.w_yaxis.set_ticklabels(ylabels)

values = np.linspace(0.2, 1., xposM.ravel().shape[0])
colors = cm.rainbow(values)
ax1.bar3d(xposM.ravel(), yposM.ravel(), dz*0, dx, dy, dz, color=colors)
plt.show()

which gives:

you can also use the values array proportional to dz:

values = (dz-dz.min())/np.float_(dz.max()-dz.min())




回答2:


As the error suggests, your result list has to contain integers, and not strings. You can convert it to integers with list comprehension:

result = [[int(i) for i in sublist] for sublist in result]

Or, better yet, you can use np.array:

import numpy as np
result = np.array(result, dtype=np.int)

Update:

As bar3d documentation (and example) suggest, ipos arrays should hold the positions of bars; di arrays should hold the distances between bars. Your xpos and ypos lists hold what is called the tick labels. So, you need to change these and then set tick labels of relevant axes to given xpos and ypos. According tho the example provided, you can do it in the following way:

xpos, ypos = np.meshgrid(np.arange(5)+0.5, np.arange(7)+0.5)
xpos = xpos.flatten()
ypos = ypos.flatten()
zpos = np.zeros(5*7)
dx = np.ones_like(zpos)
dy = dx.copy()
dz = result.flatten()
xticks=['','10/11/2013','10/12/2013','10/13/2013','10/14/2013','10/15/2013']
yticks=['','A1','C1','G1','M1','M2','M3','P1']
ax1.set_xticklabels(xticks)
ax1.set_yticklabels(yticks)


来源:https://stackoverflow.com/questions/23670178/matplotlib-3d-bar-chart-axis-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!