Назначьте цвет с помощью Seaborn на основе названия столбца - PullRequest
0 голосов
/ 26 июня 2019

Я пытаюсь создать 4 типа графиков, обобщающих мои данные.Я включил код для создания двух типов диаграмм.Я перебираю цветовую палитру cabon seaborn, чтобы получить уникальный цвет для каждой диаграммы.Однако я хотел бы, чтобы цвета были согласованы для каждого столбца в моем наборе данных.

Я создал несколько строк поддельных данных.Мои данные выглядят следующим образом:

         Time  type1  type2  type3
0  2015-01-01    100    200    300
1  2015-02-01    150    250    350
2  2015-03-01    300    300    300
3  2015-04-01    350    350    350

Код:

#Setting up data 
import warnings
import itertools
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
import sys
import seaborn as sns 

data = [{'Time': '201501','type1': 100, 'type2': 200, 'type3':300}, 
        {'Time': '201502' ,'type1':150, 'type2': 250, 'type3': 350}, 
        {'Time': '201503' ,'type1':300, 'type2': 300, 'type3': 300}, 
        {'Time': '201504' ,'type1':350, 'type2': 350, 'type3': 350}] 

data = pd.DataFrame(data) 

#Data prep

#setting index
data['Time']=pd.to_datetime(data['Time'], format='%Y%m')
data.set_index(['Time'], inplace=True)
#setting type for line graph
data=data.astype(float)

data

palette = itertools.cycle(sns.color_palette(palette=sns.colors.crayons))



############################# LINE PLOT ##################################################   

#this loops over each column in my data set and produces a graph

for i in data:  # Loop over all columns except 'Location'
    sns.set() #defaults the background
    fig, ax = plt.subplots()
    sns.set(style="ticks") 
    sns.lineplot(x=data.index,y=i,data=data,color=next(palette))  # column is chosen here
    sns.despine(offset=10, trim=True) 
    fig.set_size_inches(18,12)
    ax.set_title('{} History'.format(i), fontweight='bold')

    plt.savefig('{}.pdf'.format(i), bbox_inches='tight')  #sets file name based on column name


############################# VIOLIN PLOT ###############################################         
for i in data:  # Loop over all columns 
    sns.set() #defaults the background
    fig, ax = plt.subplots()
    sns.set(style="ticks") #darkens grid lines
    sns.violinplot(y=i, data=data,color=next(palette))  #sets which column to use
    sns.despine(offset=10, trim=True) 
    fig.set_size_inches(18,12)
    ax.set_title('{} Violin Plot'.format(i), fontweight='bold') #sets chart title based on column
    plt.savefig('{}_violin.pdf'.format(i), bbox_inches='tight')  #sets file name based on column name

enter image description here enter image description here

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

Ответы [ 2 ]

1 голос
/ 26 июня 2019

Проблема возникает, поскольку вы продолжаете использовать color=next(palette) для каждого вызова.То, что вы ищете, это постоянное отображение между именем столбца и цветом.Минимальные изменения, необходимые в вашем коде:

...
palette = itertools.cycle(sns.crayon_palette(sns.colors.crayons))  # I get an exception for your version, but I guess this is equivalent to what you meant

palette = dict(zip(data.columns, palette)) # this creates a mapping between columns and colors

...
for i in data: 
    ...
    sns.lineplot(x=data.index, y=i, data=data, color=palette[i])
    ...

Таким образом, каждый раз, когда вы рисуете линию, используемый цвет соответствует определенному столбцу, а не непрерывно рисуется из функции next итератора..

1 голос
/ 26 июня 2019

Цвета выбираются из палитры цветов с бесконечной цикличностью :

palette = itertools.cycle(sns.color_palette(palette=sns.colors.crayons))
sns.lineplot(..., color=next(palette)) 
...
sns.violinplot(..., color=next(palette))  

Каждый раз, когда вызывается next(palette), возвращается следующий цвет из цикла.Таким образом, не существует цветовой окраски между линейными сюжетами и скрипками (если только по чудесному совпадению или по замыслу len(data.columns) не кратно len(sns.colors.crayons)).

Один способ получить цвета линейной сюжета и скрипкибыть скоординированным, это сбросить палитру перед каждым циклом:

palette = sns.color_palette(palette=sns.crayon_palette(sns.colors.crayons))
new_palette = itertools.cycle(palette)
for i in data:  # Loop over all columns except 'Location'
    ...
    sns.lineplot(x=data.index, y=i, data=data, color=next(new_palette))

...

new_palette = itertools.cycle(palette)
for i in data:  # Loop over all columns 
    ...
    sns.violinplot(y=i, data=data, color=next(new_palette))

Вверху, palette - это просто список.new_palette - бесконечно циклический итератор.Создавая new_palette перед каждым for-loop, next(new_palette) будет возвращать одинаковые цвета в одинаковом порядке для обоих for-loop с.

В качестве альтернативы, возможно, более простым способом достижения желаемого результата являетсяобъедините два цикла for в один, чтобы вы могли вызывать lineplot и vionlinplot в одной и той же итерации и передавать один и тот же цвет для обоих вызовов функций.Разбиение кода на функции может помочь прояснить смысл кода и сохранить его аккуратным.

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

def make_data():
    data = [{'Time': '201501', 'type1': 100, 'type2': 200, 'type3': 300},
            {'Time': '201502', 'type1': 150, 'type2': 250, 'type3': 350},
            {'Time': '201503', 'type1': 300, 'type2': 300, 'type3': 300},
            {'Time': '201504', 'type1': 350, 'type2': 350, 'type3': 350}]

    data = pd.DataFrame(data)
    data['Time'] = pd.to_datetime(data['Time'], format='%Y%m')
    data.set_index(['Time'], inplace=True)
    data = data.astype(float)
    return data

def make_lineplot(data, i, color):
    fig, ax = plt.subplots()
    sns.set(style="ticks")
    sns.lineplot(x=data.index, y=i, data=data, color=color)  
    sns.despine(offset=10, trim=True)
    fig.set_size_inches(18, 12)
    ax.set_title('{} History'.format(i), fontweight='bold')
    plt.savefig('{}.pdf'.format(i), bbox_inches='tight')

def make_violinplot(data, i, color):
    fig, ax = plt.subplots()
    sns.set(style="ticks")  
    sns.violinplot(y=i, data=data, color=color)  
    sns.despine(offset=10, trim=True)
    fig.set_size_inches(18, 12)
    ax.set_title('{} Violin Plot'.format(i), fontweight='bold')
    plt.savefig('{}_violin.pdf'.format(i), bbox_inches='tight')

data = make_data()


palette = itertools.cycle(sns.color_palette(palette=sns.colors.crayons))
# I had to use the line below to get the code to run
# palette = itertools.cycle(sns.color_palette(palette=sns.crayon_palette(sns.colors.crayons)))

for i, color in zip(data, palette):  
    make_lineplot(data, i, color)
    make_violinplot(data, i, color)
...