简体   繁体   English

Python:基于 MultiIndex 的彩色熊猫数据框

[英]Python: Color pandas dataframe based on MultiIndex

Consider this MultiIndex dataframe考虑这个 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'])

df

and this color dictionary还有这本彩色词典

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

where the first three items of the tuple are RGB values and the fourth item is the transparency alpha.其中元组的前三项是 RGB 值,第四项是透明度 alpha。

How can the df be colored based on the level_0 index?如何根据 level_0 索引对 df 进行着色?

This result would be nice to have:这个结果会很好:

df_level_0

But this one here I would consider fine art:但这里的这个我会考虑美术:

df_art

In the latter style, the lighter cells would have the same RGB settings but a transparency of 0.25.在后一种样式中,较亮的单元格将具有相同的 RGB 设置,但透明度为 0.25。

You can use Styler.set_table_styles for set styles only first level of MultiIndex :您可以使用Styler.set_table_styles来设置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)

Second is also possible, but more complicated:第二种也是可能的,但更复杂:

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)

@jezrael has done the art! @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)

Compared to @jezrael's solution, the above is even shorter.与@jezrael 的解决方案相比,以上内容更短。

I also like that the solution doesn't depend on index labels being ordered integers.我也喜欢该解决方案不依赖于有序整数的索引标签。 Note that I'm using strings (at least for the second index level).请注意,我使用的是字符串(至少对于第二个索引级别)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM