Вот проблема при построении кадра данных:
Кадр данных выглядит как
i ii n b
0 1 0 3 0
1 4 1 5 0
2 4 0 1 5
3 4 1 2 6
4 6 0 3 0
5 6 1 4 3
(код для создания ниже). Я хотел бы построить столбцы с накоплением для тех же значений i
, и я хочу, чтобы столбцы принадлежали группам согласно ii
. Когда я выбираю только определенные строки в фрейме данных, у меня возникают проблемы с графиком, вынуждая меня явно преобразовывать столбцы фрейма данных (которые извлекаются как pandas Series) в списки. (Обратите внимание, что я не могу использовать pivot
, поскольку у меня есть несколько строк для некоторых (i
, ii
) комбинаций.)
Почему я не могу напрямую передать Series в matplotlib.pyplot.bar()
(код для рисунок 3) Почему использование Series влияет на ширину баров, которая не может быть переопределена явным аргументом width
?
Есть ли способ получить желаемый график лучше?
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'i':[1,4,4,4,6,6], 'n':[3,5,1,2,3,4]})
df['ii'] = df.index % 2
df2 = df.set_index(['i', 'ii'])
df2["b"] = df2.groupby(level='i')['n'].cumsum() - df2.n
df2.reset_index(inplace=True)
# This produces expected outcome
plt.figure(1)
plt.clf()
ix = df2[df2.ii==0]
plt.bar(x=list(ix.i), height=ix.n, bottom=list(ix.b))
ix = df2[df2.ii==1]
plt.bar(x=list(ix.i), height=ix.n, bottom=list(ix.b))
plt.show()
plt.figure(2)
plt.clf()
ix = df2[df2.ii==0]
plt.bar(x=ix.i, height=ix.n, bottom=list(ix.b))
ix = df2[df2.ii==1]
# The following line will draw a bar with unexpected width of bar
plt.bar(x=ix.i, height=ix.n, bottom=list(ix.b))
plt.show()
plt.figure(3)
plt.clf()
plt.show()
ix = df2[df2.ii==0]
plt.bar(x=ix.i, height=ix.n, bottom=ix.b)
ix = df2[df2.ii==1]
# The following line will fail
plt.bar(x=ix.i, height=ix.n, bottom=ix.b)
# error:
# TypeError: only size-1 arrays can be converted to Python scalars
# apparently matplotlib tries to set line width
Желаемый выход: ![Desired bar plot output](https://i.stack.imgur.com/xztSR.png)