2

I have a dataframe that looks like following:

      date         shop    success
1     12/06/2020   A       0.99
2     15/06/2020   A       0.95
3     17/07/2020   B       0.94
4     22/07/2020   B       0.97
...

I would like to plot a 3d histogram similar to this type:

example 3d hist

The three dimensions would be:

  • x: date
  • y: shop
  • z: success

I went through many websites, but couldn´t figure out a way to do it. I am pretty new with programming.

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
cate
  • 121
  • 1
  • 1
  • 4
  • Related to [this question](https://stackoverflow.com/questions/56336066/plotting-pandas-crosstab-dataframe-into-3d-bar-chart/56337856#56337856). – Quang Hoang Aug 12 '20 at 16:31

1 Answers1

3

Short Answer: It can be done but you have to modify your DataFrame structure.

Long Answer:

Necessary libraries:

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

The columns "Date" and "Shop" in your Dataframe are not numerical value. This means, you have to construct the graph without them and then use them to label the ticks on the axes. So lets firs constrict the empty graph. This is the dataframe structure you will need.

df = pd.DataFrame({"A": [0.0, 0.0, 0.0, 0.0],"B": [0.0, 0.0, 0.0, 0.0]})

You need to group all the values by the "Shops" and use "Shops" your main variable!

# Setting length and wight of the bars
dx, dy = .9, .01

# prepare 3d axes
fig = plt.figure(figsize=(6,6))
ax = Axes3D(fig)

# set bar positions on axes
xpos=np.arange(df.shape[0])
ypos=np.arange(df.shape[1])

# set the ticks in the middle of the bars
ax.set_xticks(xpos + dx/2)
ax.set_yticks(ypos + dy/2)

# create X, Y grid 
xpos, ypos = np.meshgrid(xpos, ypos)
xpos = xpos.flatten()
ypos = ypos.flatten()

# set the start of the bar to 0
zpos=np.zeros(df.shape).flatten()

# the bar heights these are the values under the column A and B
dz = df.values.ravel()

# ploting the barchart
ax.bar3d(xpos,ypos,zpos,dx,dy,dz)

# Labeling the ticks. For simplicity's sake I used lists for labeling but you can also iterate through columns "Date" and "Shop" to get the label values
ax.w_yaxis.set_ticklabels(["A", "B"])
ax.w_xaxis.set_ticklabels(["12/06/2020", "15/06/2020", "17/07/2020", "22/07/2020" ])

# Label the axes
ax.set_xlabel("Date")
ax.set_ylabel("Shop")
ax.set_zlabel("Success")

plt.show()

Output:

enter image description here

Perfect! As you can see we have our base with shops A & B on one axis and dates on the other. Now we can input some data into the original DataFrame and define "Success" Z values.

df = pd.DataFrame({"a": [0.1, 0.2, 0.3, 0.4],"b": [0.2, 0.3, 0.4, 0.5]})

enter image description here

The more shops you have the more Axes you'll have...

df = pd.DataFrame({"a": [0.1, 0.2, 0.3, 0.4],"b": [0.2, 0.3, 0.4, 0.5], "c": [0.1, 0.4, 0, 1.4]})

enter image description here

You can style the bars with traditional arguments like "alpha=" and "color=" but keep in mind that you have several columns so you have to provide lists for each argument and not a single value.

Cheers :)

Geom
  • 1,491
  • 1
  • 10
  • 23