将 Pandas Styler 应用于 MultiIndex 列表
Posted
技术标签:
【中文标题】将 Pandas Styler 应用于 MultiIndex 列表【英文标题】:Apply Pandas Styler to MultiIndex list 【发布时间】:2021-02-12 23:59:53 【问题描述】:我有一个多索引数据透视表,我正在从数据框制作如下所示:
pivot_summary = pd.pivot_table(df, index=['Team', 'Associate Name'], columns=['Date'], values=['Call Transfers'], aggfunc=sum, fill_value=0, margins=True, margins_name='Grand Total')
然后我有一个名为“SubTotals”的函数,它计算每个团队的总数并将它们添加到多索引中的第 1 级。
def SubTotals(df):
'''
The purpose of this function is to add sub-totals to each individual team
'''
#create a dataframe with the totals of each team
sub_totals = df.sum(level=0)
#create variable that stores string of team # + 'Total'
sub_totals_str = sub_totals.index.str[:] + ' Total'
#add the subtotals for each team to the main dataframe
final_df = df.append(sub_totals.assign(Team=sub_totals_str).set_index('Team', append=True)).sort_index()
#drop the duplicate "Grand-Total" row at the bottom
final_df.drop(final_df.tail(1).index, inplace=True)
#create string variables of both index(Multi-level index) to zip into tuples
index_level_0 = sub_totals.index.tolist()
index_level_1 = sub_totals_str.tolist()
#remove duplicate "Grand Total" from second index
index_level_1[-1] = ''
#zip index to pass through formatting function
team_totals_index = list(zip(index_level_0,index_level_1))
return final_df, team_totals_index
到目前为止,一切都很好,我得到了每个团队的小计,这正是我想要的。我卡住的地方是我想突出显示“teams_totals_index”变量中的所有行。我正在尝试创建一个函数“highlight_rows”,它将多索引列表作为参数并在匹配时突出显示。我见过很多使用 lambda 代替的示例,它已作为粗略的检查,例如:final_df.style.apply(lambda x: ['background: lightgreen' if x.name==('Grand Total','') else '' for i in x], axis=1)
产生我正在寻找的结果,它完全突出显示多索引('Grand Total','')行,但我也想突出所有其他团队。我不想将每个索引硬编码到 lambda 函数中,因为团队的数量是动态的。
我曾尝试使用 lambda 函数来创建我自己的示例,但我没有成功。以下是我尝试过的。
def highlight_rows(x, index_list):
'''
highlight the maximum Totals of each team and Grand Total.
'''
df_styler = x.copy()
b_color = 'background: lightgreen'
for index_0, index_1 in index_list:
df_styler.loc[index_0, index_1] = b_color
return df_styler
然后我尝试申请final_df.style.apply(highlight_rows, index_list=team_totals_index, axis=1)
但我得到一个 ValueError:长度不匹配,预期值 32,新轴有 22 个元素
我也试过了:
def highlight_rows(x, index_list):
'''
highlight the maximum Totals of each team and Grand Total.
'''
for index_0, index_1 in index_list:
if x.name== (index_0, index_1):
return ['background: lightgreen']
else:
return ''
但我也收到相同的 ValueError:长度不匹配,预期值 1 个元素,新值有 22 个元素。
基本上我想遍历我的列表“total_teams_index”,其中包含我想要突出显示的多级索引。任何关于我如何实现这一点的见解将不胜感激。
【问题讨论】:
【参考方案1】:虽然我似乎无法将其构建为一个函数并使其工作,但我找到了一个可行的解决方案,而无需对每个索引对进行硬编码。我正在使用方法链按照文档的建议逐段构建样式。
final_df.style.\
apply(lambda x: ['background-color: #FF9900'
if x.name in team_totals_index else 'background-color:#FFCC99' for i in x], axis=1).\
apply(lambda x: ['font-weight: bold' if x.name in team_totals_index else '' for i in x], axis=1).\
apply(lambda x: ['border-top-style:solid' if x.name in team_totals_index else '' for i in x], axis=1).\
apply(lambda x: ['border-bottom-style:solid' if x.name in team_totals_index else '' for i in x], axis=1)
我个人不喜欢重复使用同一个循环,但它符合我的目的,并且完全按照需要设置所有样式。让所有这些工作的关键是if x.name in [list containing index pairs]
,而不是像上面的示例中所示尝试迭代每个索引对。我希望这可以帮助任何遇到并且仍然可以使用一种不那么冗长/功能友好的方式来构建它的人。
【讨论】:
以上是关于将 Pandas Styler 应用于 MultiIndex 列表的主要内容,如果未能解决你的问题,请参考以下文章