当前位置: 首页 > news >正文

如何创建样式优美的 Streamlit Dataframes,第二部分:使用 AgGrid

原文:towardsdatascience.com/how-to-create-well-styled-streamlit-dataframes-part-2-using-aggrid-dbff2d52f6a2

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8d687f292355e8adb944c7b0f24d5d4e.png

在我之前的文章中,我们介绍了如何使用 pandas Styler 对象创建美观的样式化数据框。在这篇文章中,我想向大家介绍第二种选择:Streamlit AgGrid。我将分享如何构建类似上面显示的数据框。阅读完这篇文章后,你将了解:

  1. AgGrid 内部的关键组件。这些是gridOptions()configure_column()configure_default_column()configure_side_bar().

  2. 启用通过直接 UI 过滤和聚合表格的主要选项。不再需要为简单的转换构建临时查询!

  3. 使用 JavaScript 函数使数据框更美观。如果你想要,你可以将它们复制粘贴到你的代码中。或者查看我的 Git 仓库。

免责声明 1:我与 AgGrid 没有任何关联或合作关系。我只是发现这个开源产品非常有价值。AgGrid 确实有一个付费的分层产品,但本博客将仅使用 AgGrid 的免费组件。

免责声明 2:所有图像和 GIF 都是我自己创作的,除非另有说明。


什么是 AgGrid

AgGrid 是一个强大且可定制的表格组件,你可以在 Web 应用程序中使用它以表格格式显示和操作大量数据。我找到的最佳类比是,它是Web 应用版本的 Excel。想象一下,它是一个超级增强的表格,不仅显示数据,还允许用户以多种方式与之交互,例如编辑单元格、聚合和旋转,甚至与图表集成。它实际上被许多企业使用。

现在,AgGrid 是使用 JavaScript 构建的 😱😱😱。所以,是的,有一些学习要做。但,你不需要成为 JavaScript 专家!这要归功于 Pablo Fonseca,他将 JavaScript AgGrid 组件的功能迁移到了 Streamlit 应用程序中。


理解 AgGrid 的基本组件

我开始我的 AgGrid 之旅是通过阅读 Ahmed Besbes 的文章:7 个理由说明为什么你应该使用 Streamlit AgGrid 组件 [2]。这是一个很好的起点,让我理解了为什么我想使用 AgGrid。然而,我缺少一个全面的教程来了解如何使用 AgGrid。在本节中,我将尝试涵盖使 AgGrid 在我脑海中变得清晰的概念。

基本 AgGrid:你只需要一个 dataframe 和 gridOptions 对象

AgGrid 方法有很多选项……请查看下面的截图。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/76395afe91d81e57687780625d10e186.png

图片来自文档并由作者编辑

实际上,你只需要两个参数dataframegridOptions(黄色突出显示)。就是这样。只需传递 dataframe,AgGrid 就会自带一些酷炫的功能。

standard_AgGrid=AgGrid(df,gridOptions=GridOptionsBuilder.from_dataframe(df).build())# You can see how you don't even need the st.dataframe() Streamlit method.# Just by calling AgGrid, the rendering will automatically happen.

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3717036988d491e4f4cb1b9e48ebbfed.png

AgGrid 默认将允许你排序、筛选移动列。与默认的 Streamlit *st.dataframe()*方法相比,这是一个很好的补充。下面是一系列 GIF,展示了默认 AgGrid 在功能方面为你提供了什么。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/74c211d2b744e4cb5ded0ab2a95e41e3.png

这就是如何选择和取消选择列

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1088a37d9f4df8f27b349b57b0fb29e1.png

这就是如何重新排序列

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/addf67e46e048cf2722f8cea78ba4e4b.png

这就是如何筛选数据

valueGetter 与 valueFormatter

要开始为我们的 dataframe 添加一些漂亮的格式,我们首先需要了解valueGettervalueFormatter的作用。我将在稍后解释基本理论并展示示例。

  • valueGetter用于检索计算应在单元格中显示的值。它可以用来操作或合并来自不同列的数据或执行计算。但不涉及格式化

  • valueFormatter用于格式化单元格中的值以供显示。它不会改变实际值,只是改变显示时的外观。

//Imagine you have a table where you store product prices,//but you want to display the price including tax(10%)//You can use valueGetter to calculate the price including tax:valueGetter:function(params){returnparams.data.price*1.10;//Add10%tax to the original price}//Instead of having4decimal points,you might want to DISPLAY only//1decimal pointandadd a currency symbol.//This what valueFormatterisfor.valueFormatter:function(params){return'$'+params.value.toFixed(1);//Display valueascurrency}

但如何将这段 JavaScript 代码注入我们的 Python & Streamlit 代码中?

使用st_agrid包内提供的JsCode。请查看下面的代码示例:

fromst_aggridimportAgGrid,GridOptionsBuilder,JsCode# Define JsCode for valueGetter (convert cents to dollars)value_getter=JsCode(''' function(params) { return params.data.price_cents / 100; // Convert cents to dollars } ''')# Define JsCode for valueFormatter (format as currency)value_formatter=JsCode(''' function(params) { return '$' + params.value.toFixed(2); // Format the value as currency } ''')

当我们使用configure_column()时,你将学习如何使用这些value_gettervalue_formatter


configure_column()是格式化魔法发生的地方

默认的 AgGrid 视图有一些很好的开箱即用的功能(排序、筛选、列选择和拖动列)。然而,输出有点单调… 🥱

要让它更好,我们需要结合一个value_gettervalue_formatterJavaScript 函数集,并在configure_column()中使用它们。

不幸的是,文档不是很详细,但我将向你展示如何完成这些操作。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f7facbf1436e65884d8bc284489fb2ab.png

图片来自官方文档。关于configure_column的文档很少。只有一个other_column_properties 参数

清理列标题

如果你只想以不同的方式显示列名,你不需要在数据框中重命名列。你可以通过header_name参数直接将其传递给configure_column()函数。

fromst_aggridimportAgGrid,GridOptionsBuilder grid_builder=GridOptionsBuilder.from_dataframe(df)# Renaming "Period_1" to "Period 1"grid_builder.configure_column('Period_1',header_name='Period 1')# Build grid optionsgridOptions=grid_builder.build()grid_response=AgGrid(df,gridOptions=gridOptions,)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/963ab76f865c349c296a1528d4fa67be.png

将"Period_1"重命名为"Period 1"

货币格式化

你想在数字前添加货币符号,分隔千位并强制使用一定数量的小数点吗?让我们第一次使用value_gettervalue_formatterJsCode

下面的代码执行以下操作:

  1. 定义单元格将使用哪个值。currency_getter将使用我们传递给它的字段中的值。

  2. 定义你希望在单元格中显示的值。currency_formatter将返回一个currency_symbol + formattedNumber

  3. 将变量传递到我们的JsCode公式中。使用cellRendererParams。例如,currency_formatter将如何知道使用哪个符号和多少小数点?cellRendererParams允许我们将变量传递到我们的 JavaScript 函数中。

  4. 启用 Streamlit 渲染自定义 JavaScript 代码。AgGrid()中使用allow_unsafe_jscode=True

currency_formatter=JsCode(""" function(params) { if (params.value == null || params.value === undefined) { return ''; } var decimalPoints = params.column.colDef.cellRendererParams.decimalPoints || 0; var currencySymbol = params.column.colDef.cellRendererParams.currencySymbol || '€'; var value = params.value; // Format the number with thousand separators and decimal points var formattedNumber = value.toLocaleString('en-US', { minimumFractionDigits: decimalPoints, maximumFractionDigits: decimalPoints }); return currencySymbol + formattedNumber; } """)currency_getter=JsCode(""" function(params) { return params.data[params.colDef.field]; } """)grid_builder=GridOptionsBuilder.from_dataframe(df)grid_builder.configure_column('Period_1',header_name='Period 1',type=['numericColumn','numberColumnFilter','customNumericFormat'],valueGetter=currency_getter,valueFormatter=currency_formatter,cellRendererParams={'decimalPoints':0,'currencySymbol':'€',})# Build grid optionsgridOptions=grid_builder.build()grid_response=AgGrid(df,gridOptions=gridOptions,allow_unsafe_jscode=True,)

使用这个来表示Period1*、Period2Difference*,我们得到以下结果

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/64d4ee1e3d323b1f486bac3c45ff58a2.png

货币格式化

百分比变化格式化

如果你已经理解了上面的代码片段,那么下一个将很容易理解。

percentage_formatter=JsCode(""" function(params) { if (params.value == null) { return ''; } var decimalPoints = params.column.colDef.cellRendererParams.decimalPoints || 2; return (params.value * 100).toFixed(decimalPoints) + '%'; } """)percentage_getter=JsCode(""" function(params) { return params.data[params.colDef.field]; } """)# jumping directly to configure_column()grid_builder.configure_column('Percentage Change',header_name='Percentage Change (%)',type=['numericColumn','numberColumnFilter','customNumericFormat'],valueGetter=percentage_getter,valueFormatter=percentage_formatter,cellRendererParams={'decimalPoints':1,},)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/33d4d3044746527b881720fb2368b7a5.png

百分比变化格式化

突出显示单元格背景

我们如何重新创建我们在使用Styler对象时显示的绿色和红色渐变?

  1. 到现在为止,你应该知道我们首先需要创建一个JsCode函数。这个函数比较长,所以最好查看我的仓库。

  2. 但我们没有看到如何传递这个 UI 自定义格式化。这是通过configure_column()中的cellStyle参数完成的。

# Check my git repo for the function detailscellStyle=JsCode("""function(params) {...}""")grid_builder.configure_column('Percentage Change',header_name='Percentage Change (%)',type=['numericColumn','numberColumnFilter','customNumericFormat'],valueGetter=percentage_getter,valueFormatter=percentage_formatter,cellRendererParams={'decimalPoints':1,'minValue':df['Percentage Change'].min(),'maxValue':df['Percentage Change'].max()},cellStyle=cellStyle,# here is where we format the UI appearance of a cell)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/d864791e39621c392da30bda6d6cab99.png

突出显示单元格背景

添加表情符号

因为表情符号只是单元格中的额外字符,所以我们不需要value_getter,只需要value_formatter。记住,只有当你需要value_formatter对单元格执行操作(乘以 100、四舍五入等)时,你才需要value_getter。在这种情况下,不需要对表情符号进行操作。函数很简单。

# Define JsCode for emoji formattingmedalFormatter=JsCode(""" function(params) { if (params.value == null || params.value === undefined) { return ''; } var val = params.value; if (val === 1) { return val + ' 🥇'; } else if (val === 2) { return val + ' 🥈'; } else if (val === 3) { return val + ' 🥉'; } else { return val; } } """)# Define JsCode for country formattingcountryFormatter=JsCode(""" function(params) { if (params.value == null || params.value === undefined) { return ''; } var countryEmojis = { "US": "🇺🇸 ", "IN": "🇮🇳 ", "BR": "🇧🇷 ", "ES": "🇪🇸 ", "AR": "🇦🇷 ", "IT": "🇮🇹 ", "EG": "🇪🇬 " // Add more countries as needed }; var countryCode = params.value; var emoji = countryEmojis[countryCode] || ''; return emoji + ' ' + countryCode; } """)# jumping directly to configure_column()grid_builder.configure_column('Percentage Change rank',header_name='Percentage Change rank',type=['numericColumn','numberColumnFilter','customNumericFormat'],valueFormatter=medalFormatter,)grid_builder.configure_column('Country',header_name='Country',type=['textColumn','stringColumnFilter'],valueFormatter=countryFormatter,)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f2855f6b1bf5216dbffbecdec39a161c.png

添加表情符号

添加条形图

在 Excel 中,我们多次看到单元格的格式化,其中单元格背景有条纹。我们可以在 AgGrid 中实现相同的效果(类似于突出单元格背景部分,请检查我的仓库中的代码。这里粘贴太长了](https://github.com/JoseParrenoGarcia/Streamlit-pretty-dataframes/blob/5497afa74c46a88b95d00f163561ab57e78f7b4c/utils/aggrid_styling.py#L90))。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/adfd6d79751d28532197b251aa438761.png

在第 1 期和差异中添加条形图。注意,当存在负数(差异列)时,条形图使用单元格的中间作为锚点渲染。


改变整体表格 UI 显示

到目前为止,我们确实使数据框的单元格变得更漂亮了。AgGrid 还允许控制与整个表格相关的功能。例如:

  • 手动设置表格的整体高度和/或宽度

  • 改变表格的主题

让我们看看一些这些示例:

手动设置表格的整体高度

默认情况下,AgGrid 将在表格末尾添加空白。请查看下面的截图:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8c3718db353679dbf9d23d8a60c1bfec.png

要控制表格的高度,非常简单;只需使用height参数。在下面的代码片段中,我决定使用每行 60px,这仍然会添加空白,但您可以将其更改为您方便的值。

grid_response=AgGrid(df,gridOptions=gridOptions,allow_unsafe_jscode=True,height=min(2000,(len(df))*60),# 60px per row or 2000px)

改变表格的主题

在 Streamlit AgGrid 中,您只有 4 个选项可以更改主题:streamlitbalhamalpinematerial。我的默认主题是balham,因为它是最密集的表格。但下面您可以看到每个主题的列和行的宽度。

grid_response=AgGrid(df,gridOptions=gridOptions,allow_unsafe_jscode=True,height=min(2000,(len(df))*60),# 60px per row or 2000pxfit_columns_on_grid_load=False,theme='balham',# options: streamlit, alpine, balham, material)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/66caa4b3b403aba8aa5d7a0c75b929f4.png

主题:streamlit

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c5097eb82737d2c263b2d78df1dfa632.png

主题 alpine

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/130e5a60ebc6a0da4709f441f8b5df1e.png

主题 material

添加分页

分页对于处理大数据集是必不可少的。本博客文章中使用的数据只有 7 行长,但如果我们配置分页以每 3 行创建一页,它看起来会是这样。

# Enable paginationgrid_builder.configure_pagination(paginationAutoPageSize=False,paginationPageSize=3)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4dc75cb1c1a8e924196dfdafd884c06b.png

3 行分页


将 AgGrid 对象传递以供以后使用

记得 AgGrid 提供的过滤行为有多酷吗?那么,如果我们能将过滤后的数据框传递以供以后使用会怎样?为此,我们需要启用两个参数:data_return_modeupdate_mode。我们还需要创建一个新的数据框,包含网格响应数据。

grid_response=AgGrid(df,gridOptions=gridOptions,allow_unsafe_jscode=True,height=min(2000,(len(df))*60),# 60px per row or 2000pxfit_columns_on_grid_load=False,theme='balham',# options: streamlit, alpine, balham, materialdata_return_mode='FILTERED_AND_SORTED',# there are other options, read the docsupdate_mode='MODEL_CHANGED'# there are other options, read the docs)# https://streamlit-aggrid.readthedocs.io/en/docs/AgGrid.html# Create filtered dataframefiltered_df=pd.DataFrame(grid_response['data'])returngrid_response,filtered_df

检查 Streamlit 中的行为。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7ec7ce28c8b7a82d82509378a8e009e6.png

如何将(上方)过滤后的数据框(DataFrame)作为新的输出(下方)传递的示例。GIF 有点长,请等待大约 30 秒以完全渲染。


在 UI 中允许聚合

每当我创建 Streamlit 应用时,我通常需要手动创建聚合功能。例如,添加一个“按…聚合”的st.selectbox并链接到一个聚合函数。AgGrid 提供了无需编写这些小部件和函数的选项。下面是如何做到这一点:

  1. configure_default_column()中强制聚合配置

  2. 对于每一列,指定您想要执行哪种聚合函数。

grid_builder=GridOptionsBuilder.from_dataframe(df)grid_builder.configure_side_bar()grid_builder.configure_default_column(filter=True,groupable=True,value=True,enableRowGroup=True,aggFunc="sum"# sum would be applied to all columns)grid_builder.configure_column('Month',header_name='Month',type=['numericColumn','numberColumnFilter'],aggFunc=None,# If you dont want month to be passed to the "sum" aggregation, use None)grid_builder.configure_column('Percentage Change',header_name='Percentage Change (%)',type=['numericColumn','numberColumnFilter','customNumericFormat'],aggFunc="avg",# you can specify the average for % changevalueGetter=percentage_getter,valueFormatter=percentage_formatter,cellRendererParams={'decimalPoints':1,},)

AgGrid 显示聚合的方式很棒,它还允许您对“按列分组”进行深入分析。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/449a63d43da15a21392550c67fd0edbe.png

通过 UI 实时运行聚合的示例。


摘要

如果您已经看到这里,请接受我的敬意 🙇 .我知道这是一篇很长的帖子,但我想要写一些有用的详细示例。我在其他地方没有找到教程,希望这能提供类似的内容。

总结我们已涵盖的内容:

  1. AgGrid 的基本组件。

  2. 格式化表格单元格的函数。

  3. 如何格式化整个数据框。

  4. 如何将数据框作为输出对象传递

  5. 如何使用 UI 进行聚合。

您在哪里可以找到代码?

在我的仓库和实时 Streamlit 应用中:

  • Github 仓库:github.com/JoseParrenoGarcia/Streamlit-pretty-dataframes

  • Streamlit 应用:app-pretty-dataframes-in2ilkxjw2hgby4uqj9bq2.streamlit.app(当链接打开时,点击按钮以启动应用)

致谢

  • [1] Pablo Fonseca,JavaSript AgGrid 组件.

  • [2] Ahmed Besbes 文章:7 个理由说明为什么你应该使用 Streamlit AgGrid 组件.

进一步阅读

感谢阅读这篇文章!如果您对我的其他书面内容感兴趣,这里有一篇文章收集了我所有其他博客文章,按主题组织:数据科学团队和项目管理、数据故事讲述、营销与投标科学以及机器学习与建模。

所有我的书面文章都在一个地方

请保持关注!

如果您想在我发布新的书面内容时获得通知,请随意在 Medium 上关注我或订阅我的 Substack 通讯。此外,我很乐意在领英上与您聊天!

获取关于数据科学最新撰写内容的通知

Jose 的 Substack | Jose Parreño Garcia | Substack

http://www.jsqmd.com/news/125783/

相关文章:

  • LangFlow营养饮食搭配推荐系统设计
  • 如何创建优雅的 Streamlit 数据框,第一部分:使用 Pandas Styler
  • 基于IAR安装的实时控制程序部署:项目应用
  • LangFlow市场调研报告自动生成系统构想
  • LangFlow漏洞检测提示工程应用探索
  • 抖音无水印下载神器:3步搞定高清视频永久保存
  • LangFlow农业病虫害识别指导系统原型
  • Topit窗口置顶工具:5分钟学会让Mac窗口永远浮在最上层
  • LangFlow远程医疗问诊前置筛查工具
  • MDK实现Modbus RTU通信操作指南
  • 如何使用卫星图像创建你自己的 CV 数据集:来自太空的野火
  • 谷歌闪电突袭:Gemini 3免费开放引爆AI革命
  • 基于NX的智能制造解决方案:深度剖析
  • LangFlow代码生成辅助工具实战搭建
  • USB3.0引脚定义与连接器选型配合要点通俗解释
  • LangFlow轻量化部署技巧:减少资源消耗提升响应速度
  • EMI抑制在高速电路板PCB中的实践方法
  • macOS窗口管理革命:Topit置顶工具的7种高效工作流配置
  • Mac窗口管理革命:Topit如何彻底改变你的多任务工作方式
  • LangFlow后端服务通信机制:WebSocket与REST API协同
  • LangFlow面试问题生成器:HR效率提升利器
  • LangFlow会议纪要自动整理工具开发案例
  • 如何通过结合多模态信息创建强大的 AI 表示
  • LangFlow微服务架构改造建议:适应大规模应用场景
  • 基于协程的异步数据流Flow
  • ESP32-CAM UDP视频流实现:从零开始的实战案例
  • 基于ARM的工控主板设计:从零实现路径
  • milvus:存储检索高维向量的AI数据库
  • 机房工程培训ppt,太全面了
  • Pulover‘s Macro Creator完整教程:从新手到专家的自动化革命