Matplotlib с накоплением линейчатого участка: нужно поменять местами x и высоту - PullRequest
0 голосов
/ 09 января 2019

Я просматриваю некоторые данные об экологическом следе в мире и хочу составить гистограмму с накоплением для каждого типа следа, где значения, сложенные друг на друге, одинаковы, но для разных стран. Поэтому я начал использовать 2 из этих отпечатков, чтобы что-то заработало.

Это то, что я получил на работу (вроде):

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Create DataFrame from CSV file
df = pd.read_csv('countries.csv')

# Slice Series out of DF
cropFoot = df['Cropland Footprint']
grazeFoot = df['Grazing Footprint']

# Convert Series to list
cropFoot = list(cropFoot)
grazeFoot = list(grazeFoot)

X = range(163)    # the lists have 163 entries

plt.bar(X, height=cropFoot)
plt.bar(X, height=grazeFoot, bottom = cropFoot)
plt.show()

, который генерирует следующий график:

Stacked bar chart

У меня есть 5 отдельных элементов footprint, которые я хочу отобразить на оси x, чтобы данные по элементам footprint для каждой страны располагались друг над другом. По сути, сейчас на оси абсцисс показаны все 163 страны с двумя стопками. Я хочу обратного. Итак, я хочу, чтобы на каждом баре было по 5 баров по 163 странам.

Примерно так (но с 163 кусками, а не с 7):

Goal stacked bar

Неудивительно, что просто поменять местами X и высоту ... не работает. И результат не имеет никакого смысла вообще:

plt.bar(cropFoot, height=X)
plt.bar(grazeFoot, height=X, bottom = cropFoot)

plt.show()

Как это выглядит так:

Makes no sense at all.

Какой-нибудь совет, как правильно изменить это? Это набор данных, который я использую , полученный из Kaggle.

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Я думаю, что ответ @busybear, использующий гистограмму блока данных, будет лучше, но я подумал, что было бы целесообразно показать решение, которое использует matplotlib.pyplot.bar, поскольку это вопрос, для полноты.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Creates a randomized set of data to use for demonstration
n = 163
m = 5
footprints = np.zeros((m, n))
for ii in range(n):
    for jj in range(m):
        footprints[jj][ii] = random.random()*10

# This line is unnecessary for the example, it is purely for plot aesthetic
fig = plt.figure(figsize=(5, 5), dpi=200)

# colors can be replaced with any list of colors of any length >= 1
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
bottom = np.zeros(5)
for ii in range(1, n):
    for jj in range(m):
        plt.bar(jj, height=footprints[jj][ii], bottom=bottom[jj], 
                color=colors[ii % len(colors)])
        bottom[jj] = bottom[jj] + footprints[jj][ii]

plt.show()

image

0 голосов
/ 09 января 2019

Поскольку вы уже используете фрейм данных, вы можете попробовать использовать предоставленный метод bar plot, с которым немного проще работать. Для стека достаточно просто установить параметр stacked=True. Однако то, что складывается, это имена столбцов, поэтому вам придется сначала перенести свой фрейм данных. Это может выглядеть примерно так:

footprints = ['Cropland Footprint', 'Grazing Footprint', ...]  # fill with other footprints
data = df[footprints].T
data.plot.bar(stacked=True, legend=False)  # you probably don't want a legend with 163 countries

Как пример:

df = pd.DataFrame(
    np.arange(200).reshape(40, 5),
    index=[f'i{x}' for x in range(40)],
    columns=[f'c{x}' for x in range(5)]
)
df.T.plot.bar(stacked=True, legend=False)

enter image description here

...