Python: Цветной pandas кадр данных на основе MultiIndex - PullRequest
1 голос
/ 16 января 2020

Рассмотрим этот мультидексный фрейм данных

i = pd.MultiIndex.from_tuples([(0, 0), (0, 1), (1, 0), (1, 1)], names=['level_0', 'level_1'])
df = pd.DataFrame(range(0, 4), index=i, columns=['foo'])

df

и этот словарь цветов

colors = {0: (0.6, 0.8, 0.8, 1), 1: (1, 0.9, 0.4, 1)}

, где первые три элемента кортеж - это значения RGB, а четвертый элемент - альфа-прозрачность.

Как df может быть окрашен на основе индекса level_0?

Этот результат было бы неплохо получить:

df_level_0

Но вот здесь я бы рассмотрел изобразительное искусство:

df_art

В В последнем стиле более светлые ячейки будут иметь те же настройки RGB, но прозрачность 0,25.

Ответы [ 2 ]

1 голос
/ 16 января 2020

Вы можете использовать Styler.set_table_styles для установки стилей только для первого уровня MultiIndex:

i = pd.MultiIndex.from_tuples([(0, 0), (0, 1), (1, 0), (1, 1)], names=['level_0', 'level_1'])
df = pd.DataFrame(range(0, 4), index=i, columns=['foo']) 
#print (df)

import matplotlib.colors as col
colors = {0: (0.6, 0.8, 0.8, 1), 1: (1, 0.9, 0.4, 1)}

c = {k:col.rgb2hex(v) for k, v in colors.items()}
idx = df.index.get_level_values(0)

css = [{'selector': f'.row{i}.level0','props': [('background-color', c[v])]}
             for i,v in enumerate(idx)]
print (css)

df.style.set_table_styles(css)

Второй также возможен, но более сложный:

colors = {0: (0.6, 0.8, 0.8, 1), 1: (1, 0.9, 0.4, 1)}
#converts grba to integers
c1 = {k: (int(r * 255),int(g * 255),int(b * 255), a) for k, (r,g,b,a) in colors.items()}
c2 = {k: (int(r * 255),int(g * 255),int(b * 255), 0.25) for k, (r,g,b,a) in colors.items()}

#get values of first level of MulitIndex
idx = df.index.get_level_values(0)
#set css for first level
css = [{'selector': f'.row{i}.level0', 
        'props': [('background-color', f'rgba{c1[j]}')]} for i,j in enumerate(idx)]
#counter per first level for pair and unpair coloring
zipped = zip(df.groupby(idx).cumcount(), enumerate(idx))

css1 = [{'selector': f'.row{i}', 'props': [('background-color', f'rgba{c1[j]}')]} 
       if v % 2 == 0 
       else {'selector': f'.row{i}', 'props': [('background-color', f'rgba{c2[j]}')]} 
       for v,(i, j) in zipped]


df.style.set_table_styles(css1 + css)
0 голосов
/ 16 января 2020

@ jezrael сделал искусство!

import pandas as pd

i = pd.MultiIndex.from_tuples([(0, 'zero'), (0, 'one'), (0, 'two'), (1, 'zero'), (1, 'one')], names=['level_0', 'level_1'])
df = pd.DataFrame(range(0, 5), index=i, columns=['foo']) 

colors = {0: (0.6, 0.8, 0.8, 1), 1: (1, 0.9, 0.4, 1)}
#convert rgba to integers
c1 = {k: (int(r * 255),int(g * 255),int(b * 255), a) for k, (r,g,b,a) in colors.items()}
c2 = {k: (int(r * 255),int(g * 255),int(b * 255), 0.25) for k, (r,g,b,a) in colors.items()}

#get values of first level of MulitIndex
idx = df.index.get_level_values(0)
#counter per first level for pair and unpair coloring
zipped = zip(df.groupby(idx).cumcount(), enumerate(idx))

css = [{'selector': f'.row{i}', 'props': [('background-color', f'rgba{c1[j]}')]} 
       if v % 2 == 0 
       else {'selector': f'.row{i}', 'props': [('background-color', f'rgba{c2[j]}')]} 
       for v,(i, j) in zipped]

df.style.set_table_styles(css)

По сравнению с решением @ jezrael вышеупомянутое еще короче.

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

...