странное поведение с 3D-гистограммой в matplotlib в Python

У меня есть матрица Nx3 в scipy/numpy, и я хотел бы сделать из нее трехмерную гистограмму, где оси X и Y определяются значениями первого и второго столбцов матрицы, высота каждого столбца является третьим столбцом в матрице, а количество баров определяется N.

Кроме того, я хочу построить несколько групп этих матриц, каждая из которых окрашена в другой цвет («сгруппированный» трехмерный столбчатый график).

Когда я пытаюсь построить это следующим образом:

ax.bar(data[:, 0], data[:, 1], zs=data[:, 2],
               zdir='z', alpha=0.8, color=curr_color)

Я получаю очень странные полосы, как показано здесь: http://tinypic.com/r/anknzk/7< /а>

Есть идеи, почему стержни такие кривые и странной формы? Мне просто нужна одна полоса в точке X-Y, высота которой равна точке Z.


person Community    schedule 30.03.2011    source источник
comment
Глядя на документы, рассмотрите возможность использования метода bar3d: matplotlib.sourceforge.net/mpl_toolkits/mplot3d/   -  person Thomas K    schedule 30.03.2011


Ответы (1)


Вы неправильно используете аргумент ключевого слова zs. Это относится к плоскостям, на которых размещен каждый набор стержней (определяется по оси zdir). Они кривые, потому что предполагается, что набор баров, определенный вызовом ax.bar, находится в одной плоскости. Вам, вероятно, лучше вызвать ax.bar несколько раз (по одному для каждой плоскости). Внимательно следуйте этому примеру. Вы хотите, чтобы zdir было либо 'x', либо 'y'.

Изменить

Вот полный код (в значительной степени основанный на приведенном выше примере).

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

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

# this is just some setup to get the data
r = numpy.arange(5)
x1,y1 = numpy.meshgrid(r,r)
z1 = numpy.random.random(x1.shape)

# this is what your data probably looks like (1D arrays):
x,y,z = (a.flatten() for a in (x1,y1,z1))
# preferrably you would have it in the 2D array format
# but if the 1D is what you must work with:
# x is: array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
#              0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
#              0, 1, 2, 3, 4])
# y is: array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
#              2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
#              4, 4, 4, 4, 4])

for i in range(0,25,5):
    # iterate over layers
    # (groups of same y)
    xs = x[i:i+5] # slice each layer
    ys = y[i:i+5]
    zs = z[i:i+5]
    layer = ys[0] # since in this case they are all equal.
    cs = numpy.random.random(3) # let's pick a random color for each layer
    ax.bar(xs, zs, zs=layer, zdir='y', color=cs, alpha=0.8)

plt.show()
person Paul    schedule 30.03.2011
comment
что вы имеете в виду называть это один раз для каждого самолета? Можете ли вы показать пример? Я все еще не могу заставить его работать - person ; 30.03.2011
comment
Спасибо. И как я могу установить метки на каждой оси в трехмерном пространстве? Спасибо - person ; 30.03.2011
comment
В вашем коде вы не передаете ys в bar - это намеренно? - person ; 30.03.2011
comment
Он передается как layer (я думал, что это имя прояснит концепцию самолетов — вероятно, мне следовало назвать его plane). Все y одинаковы для каждого слоя/плоскости. Я выбираю первое значение, используя ys[0]. Вам нужно передать только одно значение y, если вы хотите, чтобы все они находились в одной плоскости. zs и zdir, к сожалению, названы, на мой взгляд, так как они часто (и в этом случае) расположены вдоль другой оси, отличной от z. - person Paul; 30.03.2011
comment
Я получаю сообщение об ошибке 3D-проекция недействительна. Кроме того, вы знаете, как изменить метки? - person ; 31.03.2011
comment
@ user248237: Либо вернитесь к использованию ax = Axes3D(fig), либо обновитесь до matplotlib 1.0. Попробуйте найти SO для matplotlib ticklabels - person Paul; 31.03.2011