0
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

# Given data
x_values = np.array([1, 2, 3, 4, 5, 6])
y_values = np.array([4, 6, 3, 5, 7, 6])
information = np.array([
    [0.3, 0.5, 0.1, 0.1, 0.2, 0.1],
    [0.1, 0.2, 0.1, 0.1, 0.1, 0.5],
    [0.5, 0.1, 0.1, 0.1, 0.5, 0.1],
    [0.1, 0.1, 0.2, 0.5, 0.1, 0.1],
    [0.0, 0.1, 0.5, 0.2, 0.1, 0.2]])

I have x and y values and some information to show using color on a scatter plot. Each of the column from the information array represents 5 parameters for each (x,y) point. I want to show the participation of those parameters using a spectrum of color. How can I do it?

Mamdud
  • 63
  • 5
  • 4
    The desired result is not clear: [code and plot](https://i.stack.imgur.com/kHYc8.png) – Trenton McKinney May 26 '23 at 06:16
  • 3
    @TrentonMcKinney This is my interpretation: OP has 6 points in _x-y_ plane, and associated to each point 5 parameters (a column in `information`) , and the sum of a column is always one. Then the OP asks for a method to represent this 4-way dependency using "a spectrum of color" — I have to say that, if my understanding is correct, there is no obvious way to do that. – gboffi May 26 '23 at 13:02
  • that is right interpretation @TrentonMcKinney – Mamdud May 26 '23 at 16:06
  • @gboffi could you suggest what would be the best way of visualizing such parameters? – Mamdud May 26 '23 at 16:07
  • @gboffi my understanding is that there is simply no way to represent 4 degrees of freedom in a color spectrum. You only have 3 colors to work with. Our eyes can't perceive more than that. – Joooeey May 26 '23 at 21:39
  • @Joooeey I have posted a solution that stretches the Idea of "a spectrum of color", let's see if the OP appreciates... – gboffi May 26 '23 at 21:45

1 Answers1

2

I think this is a reasonable solution, using mpl_toolkits.mplot3d.axes3d.Axes3D.bar3d

enter image description here

As you can see, there is a nasty artifact..., further there is (so it seems) a Matplotlib bug that prevents adding a legend, that is sorely needed (see this question of mine). I've added the sorely needed legend using the info Trenton McKinney provided in this comment — thank you Trenton.

Here it's the code, the only trick is how the bases array is computed

import matplotlib.pyplot as plt
import numpy as np

x = np.array([1, 2, 3, 4, 5, 6])
y = np.array([4, 6, 3, 5, 7, 6])
informations = np.array([
    [0.3, 0.5, 0.1, 0.1, 0.2, 0.1],
    [0.1, 0.2, 0.1, 0.1, 0.1, 0.5],
    [0.5, 0.1, 0.1, 0.1, 0.5, 0.1],
    [0.1, 0.1, 0.2, 0.5, 0.1, 0.1],
    [0.0, 0.1, 0.5, 0.2, 0.1, 0.2]])

bases = np.vstack(([0]*len(x), informations.cumsum(axis=0)))[:-1]

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

for n, (base, info) in enumerate(zip(bases, informations)):
    ax1.bar3d(x-0.5, y-0.5, base, 1, 1, info, label=str(n), shade=True)

plt.xlabel('X')
plt.ylabel('Y')

color = plt.rcParams['axes.prop_cycle']()
proxies = [plt.Rectangle((0, 0), 1, 1, **next(color)) for _ in informations[:,0]]
labels = 'Apricots Bananas Cherries Dates Elderberries'.split()
ax1.legend(proxies, labels, bbox_to_anchor=(1.05, 0.50), loc='center left', frameon=0)

plt.show()
gboffi
  • 22,939
  • 8
  • 54
  • 85