Измените морскую природу - PullRequest
1 голос
/ 12 апреля 2019

Я нашел этот красивый график онлайн (по-видимому, сделанный с помощью сюжета) и хотел воссоздать его с Seaborn.enter image description here

Это мой код на данный момент:

import pandas as pd
import seaborn as sns

data = ...

flierprops = dict(marker='o', markersize=3)
sns.boxplot(x="label", y="mean",palette="husl", data=data,saturation=1,flierprops=flierprops)

и это результат на данный момент:

enter image description here

Я уже вполне счастлив, но я бы хотел отрегулировать цвета линии и выброса, чтобы они соответствовали цветовой палитре husl.Как я могу это сделать?(и дополнительно: как бы я изменил ширину линии?)

1 Ответ

1 голос
/ 12 апреля 2019

Рассмотрим два решения SO:

  1. @ tmdavison's решение для редактирования объектов Line2D для линейных и точечных цветов
  2. @ решение IanHincks для освещения / затемнения цветов matplotlib для границ

Данные

import numpy as np
import pandas as pd

data_tools = ['sas', 'stata', 'spss', 'python', 'r', 'julia']

### DATA BUILD
np.random.seed(4122018)
random_df = pd.DataFrame({'group': np.random.choice(data_tools, 500),
                          'int': np.random.randint(1, 10, 500),
                          'num': np.random.randn(500),
                          'bool': np.random.choice([True, False], 500),
                          'date': np.random.choice(pd.date_range('2019-01-01', '2019-04-12'), 500)
                           }, columns = ['group', 'int', 'num', 'char', 'bool', 'date'])

Сюжет (генерирует два: исходный и скорректированный)

import matplotlib.pyplot as plt
import matplotlib.colors as mc
import colorsys
import seaborn as sns

def lighten_color(color, amount=0.5):  
    # --------------------- SOURCE: @IanHincks ---------------------
    try:
        c = mc.cnames[color]
    except:
        c = color
    c = colorsys.rgb_to_hls(*mc.to_rgb(c))
    return colorsys.hls_to_rgb(c[0], 1 - amount * (1 - c[1]), c[2])

# --------------------- SOURCE: @tmdavison ---------------------    
fig, (ax1,ax2) = plt.subplots(2, figsize=(12,6))                           
sns.set()

flierprops = dict(marker='o', markersize=3)
sns.boxplot(x="group", y="num", palette="husl", data=random_df, saturation=1, 
           flierprops=flierprops, ax=ax1)
ax1.set_title("Original Plot Output")

sns.boxplot(x="group", y="num", palette="husl", data=random_df, saturation=1, 
            flierprops=flierprops, ax=ax2)
ax2.set_title("\nAdjusted Plot Output")

for i,artist in enumerate(ax2.artists):
    # Set the linecolor on the artist to the facecolor, and set the facecolor to None
    col = lighten_color(artist.get_facecolor(), 1.2)
    artist.set_edgecolor(col)    

    # Each box has 6 associated Line2D objects (to make the whiskers, fliers, etc.)
    # Loop over them here, and use the same colour as above
    for j in range(i*6,i*6+6):
        line = ax2.lines[j]
        line.set_color(col)
        line.set_mfc(col)
        line.set_mec(col)
        line.set_linewidth(0.5)   # ADDITIONAL ADJUSTMENT

plt.tight_layout()
plt.show()

Plot Outputs


Для вашего конкретного сюжета, установите оси для коробочного графика, а затем итерируйте по художникам MPL:

fig, ax = plt.subplots(figsize=(12,6))      
sns.boxplot(x="label", y="mean",palette="husl", data=data, saturation=1,
            flierprops=flierprops, ax=ax)

for i,artist in enumerate(ax.artists):
    # Set the linecolor on the artist to the facecolor, and set the facecolor to None
    col = lighten_color(artist.get_facecolor(), 1.2)
    artist.set_edgecolor(col)    

    # Each box has 6 associated Line2D objects (to make the whiskers, fliers, etc.)
    # Loop over them here, and use the same colour as above
    for j in range(i*6,i*6+6):
        line = ax.lines[j]
        line.set_color(col)
        line.set_mfc(col)
        line.set_mec(col)
        line.set_linewidth(0.5)
...