Pandas 样式:在包括多索引在内的整行上绘制边框

Pandas Style: Draw borders over whole row including the multiindex

我在 jupyter 笔记本中使用 pandas 样式来强调此数据框中子组之间的边界:

(从技术上讲:在每一个变化的多索引处绘制边界,但忽略最低级别)

# some sample df with multiindex
res = np.repeat(["response1","response2","response3","response4"], 4)
mod = ["model1", "model2","model3","model4"]*len(res)
data = np.random.randint(0,50,size=len(mod))
df = pd.DataFrame(zip(res,mod,data), columns=["res","mod","data"])
df.set_index(["res","mod"], inplace=True)

# set borders at individual frequency
indices_with_borders = range(0,len(df), len(np.unique(mod)))
df.style.set_properties(subset=(df.index[indices_with_borders], df.columns), **{
                      'border-width': '1px', "border-top-style":"solid"}) 

结果:

现在看起来有点傻,边框只画在列上,而不是一直延伸到多索引。这将是一个更令人愉悦的风格:

有人知道如何/是否可以实现吗? 提前致谢!

s = df.style
for l0 in ['response1', 'response2', 'response3', 'response4']:
    s.set_table_styles({(l0, 'model4'): [{'selector': '', 'props': 'border-bottom: 3px solid red;'}],
                        (l0, 'model1'): [{'selector': '.level0', 'props': 'border-bottom: 3px solid green'}]},
                      overwrite=False, axis=1)
s

因为多索引会稀疏和跨越行,所以您需要小心控制行 类。这有点痛苦,但它可以满足您的需求...

s = df.style
for idx, group_df in df.groupby('res'):
    s.set_table_styles({group_df.index[0]: [{'selector': '', 'props': 'border-top: 3px solid green;'}]}, 
                       overwrite=False, axis=1)
s

我接受了 Attack68 的回答,并认为我会展示如何使其更通用,如果您在多索引中有更多级别,这将很有用。允许您按多索引中的任何级别进行分组,并在该级别的顶部添加边框。因此,如果我们想对关卡 mod 做同样的事情,我们也可以这样做:

df = df.sort_index(level=['mod'])
s = df.style
for idx, group_df in df.groupby('mod'):
    s.set_table_styles({group_df.index[0]: [{'selector': '', 'props': 'border-top: 3px solid green;'}]},
                       overwrite=False, axis=1)
s