Как я могу построить отдельные кадры данных Pandas в качестве подзаголовков?


129

У меня есть несколько Pandas DataFrames с одинаковой шкалой значений, но с разными столбцами и индексами. При вызове df.plot()получаю отдельные сюжетные изображения. на самом деле я хочу, чтобы все они находились в одном сюжете с подсюжетами, но, к сожалению, я не могу придумать решение, как это сделать, и был бы очень признателен за некоторую помощь.

Ответы:


252

Вы можете вручную создать подзаголовки с помощью matplotlib, а затем построить фреймы данных на конкретном подзаголовке, используя axключевое слово. Например, для 4 участков (2x2):

import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2, ncols=2)

df1.plot(ax=axes[0,0])
df2.plot(ax=axes[0,1])
...

Вот axesмассив, который содержит различные оси подзаголовка, и вы можете получить к нему доступ, просто индексируя axes.
Если вы хотите общую ось х, то вы можете предоставить sharex=Trueв plt.subplots.


33
Обратите внимание, что, к сожалению, .subplots()возвращает разные системы координат в зависимости от размеров массива создаваемых вами подзаголовков. Итак, если вы вернете подзаголовки, где, скажем, nrows=2, ncols=1вам нужно будет проиндексировать оси как axes[0]и axes[1]. См stackoverflow.com/a/21967899/1569221
canary_in_the_data_mine

3
@canary_in_the_data_mine Спасибо, это действительно раздражает ... ваш комментарий сэкономил мне время :) не мог понять, почему я получаюIndexError: too many indices for array
snd

9
@canary_in_the_data_mine Это раздражает, только если используются аргументы по умолчанию для .subplot(). Установите squeeze=Falseпринудительно, .subplot()чтобы всегда возвращать ndarrayв любом случае строк и столбцов.
Martin

73

Вы можете увидеть напр. в документации, демонстрирующей ответ Джориса. Также из документации вы также можете установить subplots=Trueи layout=(,)в plotфункции pandas :

df.plot(subplots=True, layout=(1,2))

Вы также можете использовать fig.add_subplot()which принимает параметры сетки подзаголовка, такие как 221, 222, 223, 224 и т. Д., Как описано в сообщении здесь . Хорошие примеры графика на фрейме данных pandas, включая подзаголовки, можно увидеть в этом блокноте ipython .


2
хотя ответ Джориса отлично подходит для общего использования matplotlib, он отлично подходит для всех, кто хочет использовать pandas для быстрой визуализации данных. Это также немного лучше соответствует вопросу.
Little Bobby Tables

Имейте в виду, что subplotsи layoutkwargs будут генерировать несколько графиков ТОЛЬКО для одного фрейма данных. Это связано, но не является решением вопроса OP о построении нескольких фреймов данных на одном графике.
Austin A

1
Это лучший ответ для использования на чистом Pandas. Для этого не требуется напрямую импортировать matplotlib (хотя обычно вы должны это делать в любом случае) и не требуется цикл для произвольных форм (можно использовать layout=(df.shape[1], 1), например).
Анатолий Макаревич

20

Вы можете использовать знакомый стиль Matplotlib, вызывая figureи subplot, но вам просто нужно указать текущую ось, используя plt.gca(). Пример:

plt.figure(1)
plt.subplot(2,2,1)
df.A.plot() #no need to specify for first axis
plt.subplot(2,2,2)
df.B.plot(ax=plt.gca())
plt.subplot(2,2,3)
df.C.plot(ax=plt.gca())

и т.д...


7

Вы можете построить несколько подзаголовков из нескольких фреймов данных pandas, используя matplotlib с простым трюком, состоящим в создании списка всех фреймов данных. Затем используйте цикл for для построения подзаголовков.

Рабочий код:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# dataframe sample data
df1 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df2 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df3 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df4 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df5 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
df6 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
#define number of rows and columns for subplots
nrow=3
ncol=2
# make a list of all dataframes 
df_list = [df1 ,df2, df3, df4, df5, df6]
fig, axes = plt.subplots(nrow, ncol)
# plot counter
count=0
for r in range(nrow):
    for c in range(ncol):
        df_list[count].plot(ax=axes[r,c])
        count=+1

введите описание изображения здесь

Используя этот код, вы можете построить подзаголовки в любой конфигурации. Вам нужно просто определить количество строк nrowи количество столбцов ncol. Также вам необходимо составить список фреймов данных, df_listкоторые вы хотите построить.


2
обратите внимание на опечатку в последней строке: это не count =+1ноcount +=1
PEBKAC

4

Вы можете использовать это:

fig = plt.figure()
ax = fig.add_subplot(221)
plt.plot(x,y)

ax = fig.add_subplot(222)
plt.plot(x,z)
...

plt.show()

3

Возможно, вам вообще не нужно использовать Pandas. Вот график matplotlib частот кошек:

введите описание изображения здесь

x = np.linspace(0, 2*np.pi, 400)
y = np.sin(x**2)

f, axes = plt.subplots(2, 1)
for c, i in enumerate(axes):
  axes[c].plot(x, y)
  axes[c].set_title('cats')
plt.tight_layout()

1

Основываясь на ответе @joris выше, если вы уже установили ссылку на подзаговор, вы также можете использовать ссылку. Например,

ax1 = plt.subplot2grid((50,100), (0, 0), colspan=20, rowspan=10)
...

df.plot.barh(ax=ax1, stacked=True)

0

Как создать несколько графиков из словаря фреймов данных с длинными (аккуратными) данными

  • Предположения

    • Есть словарь нескольких фреймов аккуратных данных
      • Создано путем чтения из файлов
      • Создается путем разделения одного фрейма данных на несколько фреймов.
    • Категории cat,, могут перекрываться, но все фреймы данных могут не содержать все значенияcat
    • hue='cat'
  • Поскольку кадры данных проходят итерацию, нет гарантии, что цвета будут отображаться одинаково для каждого графика.

    • Пользовательская цветовая карта должна быть создана из уникальных 'cat'значений для всех фреймов данных.
    • Поскольку цвета будут одинаковыми, поместите одну легенду сбоку от графиков вместо легенды на каждом графике.

Импорт и синтетические данные

import pandas as pd
import numpy as np  # used for random data
import random  # used for random data
import matplotlib.pyplot as plt
from matplotlib.patches import Patch  # for custom legend
import seaborn as sns
import math import ceil  # determine correct number of subplot


# synthetic data
df_dict = dict()
for i in range(1, 7):
    np.random.seed(i)
    random.seed(i)
    data_length = 100
    data = {'cat': [random.choice(['A', 'B', 'C']) for _ in range(data_length)],
            'x': np.random.rand(data_length),
            'y': np.random.rand(data_length)}
    df_dict[i] = pd.DataFrame(data)


# display(df_dict[1].head())

  cat         x         y
0   A  0.417022  0.326645
1   C  0.720324  0.527058
2   A  0.000114  0.885942
3   B  0.302333  0.357270
4   A  0.146756  0.908535

Создавайте сопоставления цветов и график

# create color mapping based on all unique values of cat
unique_cat = {cat for v in df_dict.values() for cat in v.cat.unique()}  # get unique cats
colors = sns.color_palette('husl', n_colors=len(unique_cat))  # get a number of colors
cmap = dict(zip(unique_cat, colors))  # zip values to colors

# iterate through dictionary and plot
col_nums = 3  # how many plots per row
row_nums = math.ceil(len(df_dict) / col_nums)  # how many rows of plots
plt.figure(figsize=(10, 5))  # change the figure size as needed
for i, (k, v) in enumerate(df_dict.items(), 1):
    plt.subplot(row_nums, col_nums, i)  # create subplots
    p = sns.scatterplot(data=v, x='x', y='y', hue='cat', palette=cmap)
    p.legend_.remove()  # remove the individual plot legends
    plt.title(f'DataFrame: {k}')

plt.tight_layout()
# create legend from cmap
patches = [Patch(color=v, label=k) for k, v in cmap.items()]
# place legend outside of plot; change the right bbox value to move the legend up or down
plt.legend(handles=patches, bbox_to_anchor=(1.06, 1.2), loc='center left', borderaxespad=0)
plt.show()

введите описание изображения здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.