3

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
2
  • Your xpos should be a list of strings ["10/11/2013", "10/12/2013", "10/13/2013", "10/14/2013", "10/15/2013"] Commented May 15, 2014 at 6:00
  • I did that...but still getting same error as mentioned above Commented May 15, 2014 at 6:15

2 Answers 2

6

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:

enter image description here

you can also use the values array proportional to dz:

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

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

Is it possible to assign random color to each row or line?
q@user3632319 I've updated the answer adding colors to each bar. Note that you can use any color scale contained in matplotlib.cm, I used the rainbow but you shoud check the others as well...
@user3632319 to change only one row or column you have to play with the values array...
@SaulloG.P.Castro Nice, I ran exactly the same code but I'm not getting the black strokes around each bar, what's wrong?
0

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)

2 Comments

I have converted my result list with reference to your above code..but still getting the same error
Yes, it seems that bar3d works the different way altogether. i'll edit my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.