Настройка аннотаций с помощью Seaborn FacetGrid

Я пытаюсь настроить некоторые рисунки с помощью модуля Seaborn в Python, но мне не удалось создать собственные метки или аннотации. У меня есть код, который генерирует следующий рисунок:

plot = sns.FacetGrid(data = data, col = 'bot', margin_titles = True).set_titles('Human', 'Bot')
bins = np.linspace(0, 2000, 15)
plot = plot.map(plt.hist, 'friends_count', color = 'black', lw = 0, bins = bins)
plot.set_axis_labels('Number Following', 'Count')
sns.despine(left = True, bottom = True)

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

Я хотел бы сделать две вещи: 1. заменить метки факторов по умолчанию, например. 'bot = 0.0' со значимым текстом и 2. нарисуйте вертикальные линии у среднего числа, следующего за каждой категорией.

Вот самодостаточный пример:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

fake = pd.DataFrame({'val': [1, 2, 2, 3, 3, 2, 1, 1, 2, 3], 'group': [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]})
plot = sns.FacetGrid(data = fake, col = 'group', margin_titles = True).set_titles('zero', 'one')
plot = plot.map(plt.hist, 'val', color = 'black', lw = 0)
sns.despine(left = True, bottom = True)

Кто-нибудь знает, как настроить FacetGrid?


person Erin Shellman    schedule 26.07.2015    source источник
comment
проверьте метод FacetGrid.set_titles.   -  person mwaskom    schedule 26.07.2015
comment
Да, пробовал, но ничего не рендерится. Любые мысли о том, чтобы сделать вертикальные линии в разных точках на каждом?   -  person Erin Shellman    schedule 26.07.2015
comment
Не уверен, что ничего не означает. Если вы пробовали что-то и не сработало, вы должны добавить это тоже к вопросу. Кроме того, гораздо легче помочь, когда в вашем вопросе есть самодостаточный пример, который кто-то может скопировать и вставить для дальнейшего развития. Возможно, вы могли бы использовать один из примеров наборов морских данных, которые используются в руководстве.   -  person mwaskom    schedule 26.07.2015
comment
Я использовал set_titles в вопросе, но мои заголовки не отображаются. Я просто включил самодостаточный пример идентичного поведения.   -  person Erin Shellman    schedule 29.07.2015


Ответы (1)


Несколько слов о set_titles.

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

Во-вторых, если вы посмотрите на строку документации для метода, вы увидите, что он не просто принимает произвольный список заголовков. Он предоставляет способ изменить способ отображения заголовка с помощью имени и значения переменной столбца:

template : string
    Template for all titles with the formatting keys {col_var} and
    {col_name} (if using a `col` faceting variable) and/or {row_var}
    and {row_name} (if using a `row` faceting variable).

Таким образом, самый простой способ получить «значимый текст» - использовать значимые данные в вашем фрейме данных. Возьмем этот пример со случайными данными:

df = pd.DataFrame({'val': np.random.randn(100),
                   'group': np.repeat([0, 1], 50)})

Если вы хотите, чтобы «группа» была zero и one, вы должны просто изменить этот столбец или создать новый:

df["group"] = df["group"].map({0: "zero", 1; "one"})

Затем скажите, что вы не хотите иметь имя переменной в заголовке, правильный способ использования FacetGrid.set_titles будет

g = sns.FacetGrid(data=df, col='group')
g.map(plt.hist, 'val', color='black', lw=0)
g.set_titles('{col_name}')

несколько гистограмм

Если вы не хотите изменять отображаемые данные, вам нужно будет напрямую установить атрибуты на осях matplotlib, например:

for ax, title in zip(g.axes.flat, ['zero', 'one']):
    ax.set_title(title)

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

Чтобы построить среднее значение, вам нужно создать небольшую функцию, которую можно передать в FacetGrid.map. Существует несколько примеров о том, как это сделать, в учебнике. В этом случае все очень просто:

def vertical_mean_line(x, **kwargs):
    plt.axvline(x.mean(), **kwargs)

Тогда все, что вам нужно, это перестроить:

g = sns.FacetGrid(data=df, col='group')
g.map(plt.hist, 'val', color='black', lw=0)
g.map(vertical_mean_line, 'val')
g.set_titles('{col_name}')

еще несколько гистограмм

person mwaskom    schedule 28.07.2015
comment
Отличный ответ. IMO проблема с кодированием данных с помощью меток, которые вы использовали бы для визуализации, заключается в том, что это исключает применение преобразований к данным позже (без многократного повторного кодирования). Например, если бы я хотел центрировать и масштабировать, мне пришлось бы преобразовать эти метки обратно в [0, 1]. Мы надеемся увидеть лучшую поддержку надписей и аннотаций рисунков в будущем. Было бы здорово иметь что-то элегантное и мощное, например, ggplot2 для Python. - person Erin Shellman; 06.08.2015
comment
@erinshellman ты видел библиотеку ggplot yhat? ggplot.yhathq.com/docs/facet_grid.html - person Paul H; 28.09.2015