|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
引言
在数据分析和处理领域,pandas作为Python的核心库之一,为我们提供了强大的数据处理能力。然而,仅仅能够处理数据是不够的,如何有效地展示和分析结果同样重要。专业的表格输出不仅能让数据更加直观,还能显著提升工作效率和职场竞争力。本文将深入探索pandas表格输出的多种方法与实用技巧,帮助读者解决数据展示难题,让数据分析结果更加专业直观。
基础表格输出方法
print()函数
最基础的输出方法是使用Python内置的print()函数。这种方法简单直接,但在处理大型数据集时可能不够美观。
- import pandas as pd
- import numpy as np
- # 创建示例数据
- data = {
- '姓名': ['张三', '李四', '王五', '赵六', '钱七'],
- '年龄': [28, 34, 29, 42, 31],
- '部门': ['技术部', '市场部', '财务部', '技术部', '人力资源部'],
- '薪资': [12000, 15000, 9000, 18000, 11000]
- }
- df = pd.DataFrame(data)
- # 使用print()输出
- print(df)
复制代码
输出结果:
- 姓名 年龄 部门 薪资
- 0 张三 28 技术部 12000
- 1 李四 34 市场部 15000
- 2 王五 29 财务部 9000
- 3 赵六 42 技术部 18000
- 4 钱七 31 人力资源部 11000
复制代码
display()函数(在Jupyter Notebook中)
在Jupyter Notebook环境中,display()函数提供了更美观的输出效果:
- # 在Jupyter Notebook中使用
- from IPython.display import display
- display(df)
复制代码
这将在Notebook中渲染出一个美观的表格,支持滚动和交互功能。
to_string()方法
to_string()方法允许我们将DataFrame转换为字符串格式,提供了更多的自定义选项:
- # 使用to_string()方法
- print(df.to_string(index=False)) # 不显示索引
- # 自定义格式
- print(df.to_string(
- index=False,
- justify='center', # 文本居中对齐
- col_space=15, # 列宽
- show_dimensions=True # 显示维度信息
- ))
复制代码
格式化输出技巧
设置显示选项
pandas提供了多种设置显示选项的方法,可以全局控制输出格式:
- # 设置显示选项
- pd.set_option('display.max_rows', 10) # 最大显示行数
- pd.set_option('display.max_columns', 10) # 最大显示列数
- pd.set_option('display.width', 1000) # 显示宽度
- pd.set_option('display.precision', 2) # 小数点精度
- pd.set_option('display.float_format', '{:.2f}'.format) # 浮点数格式
- # 创建包含浮点数的示例数据
- np.random.seed(42)
- float_data = pd.DataFrame({
- 'A': np.random.randn(5),
- 'B': np.random.randn(5),
- 'C': np.random.randn(5)
- })
- print(float_data)
- # 重置选项
- pd.reset_option('all')
复制代码
样式设置(Styling)
pandas的Styler对象提供了强大的表格样式设置功能:
- # 基本样式设置
- styled_df = df.style.set_properties(**{
- 'background-color': '#f7f7f9',
- 'color': 'black',
- 'border-color': 'white',
- 'border-style': 'solid',
- 'border-width': '1px'
- })
- # 在Jupyter Notebook中显示
- styled_df
复制代码- # 更高级的样式设置
- styled_df = df.style \
- .set_caption('员工信息表') \ # 添加标题
- .set_properties(**{'text-align': 'center'}) \ # 文本居中
- .hide_index() \ # 隐藏索引
- .background_gradient(cmap='Blues', subset=['年龄', '薪资']) \ # 背景渐变
- .highlight_max(subset=['薪资'], color='red') \ # 高亮最大值
- .highlight_min(subset=['薪资'], color='green') # 高亮最小值
- styled_df
复制代码
条件格式化
条件格式化可以根据数据值动态设置样式:
- # 条件格式化示例
- def highlight_high_salary(val):
- color = 'red' if val > 15000 else 'black'
- return f'color: {color}'
- styled_df = df.style.applymap(highlight_high_salary, subset=['薪资'])
- styled_df
复制代码- # 更复杂的条件格式化
- def style_by_department(val):
- if val == '技术部':
- return 'background-color: #e6f2ff'
- elif val == '市场部':
- return 'background-color: #fff2e6'
- elif val == '财务部':
- return 'background-color: #e6ffe6'
- else:
- return 'background-color: #f2e6ff'
- styled_df = df.style.applymap(style_by_department, subset=['部门'])
- styled_df
复制代码
高级输出方法
转换为HTML
将DataFrame转换为HTML格式,便于在网页或邮件中展示:
- # 转换为HTML
- html_table = df.to_html(
- index=False, # 不显示索引
- classes='table table-striped', # 添加CSS类
- table_id='employee_table', # 设置表格ID
- border=0, # 边框宽度
- justify='center' # 对齐方式
- )
- # 保存为HTML文件
- with open('employee_table.html', 'w', encoding='utf-8') as f:
- f.write(f"""
- <!DOCTYPE html>
- <html>
- <head>
- <title>员工信息表</title>
- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
- <style>
- body {{ padding: 20px; }}
- .container {{ max-width: 800px; margin: 0 auto; }}
- h1 {{ color: #333; }}
- </style>
- </head>
- <body>
- <div class="container">
- <h1>员工信息表</h1>
- {html_table}
- </div>
- </body>
- </html>
- """)
复制代码
转换为Markdown
将DataFrame转换为Markdown格式,便于在文档和README文件中使用:
- # 转换为Markdown
- markdown_table = df.to_markdown(
- index=False,
- tablefmt='grid',
- stralign='center',
- numalign='center'
- )
- print(markdown_table)
- # 保存为Markdown文件
- with open('employee_table.md', 'w', encoding='utf-8') as f:
- f.write("# 员工信息表\n\n")
- f.write(markdown_table)
复制代码
转换为LaTeX
将DataFrame转换为LaTeX格式,便于在学术论文和报告中使用:
- # 转换为LaTeX
- latex_table = df.to_latex(
- index=False,
- caption='员工信息表',
- label='tab:employee',
- position='htbp',
- column_format='|c|c|c|c|',
- escape=False
- )
- print(latex_table)
- # 保存为LaTeX文件
- with open('employee_table.tex', 'w', encoding='utf-8') as f:
- f.write("\\documentclass{article}\n")
- f.write("\\usepackage[utf8]{inputenc}\n")
- f.write("\\usepackage{booktabs}\n")
- f.write("\\begin{document}\n\n")
- f.write(latex_table)
- f.write("\n\\end{document}")
复制代码
转换为Excel
将DataFrame转换为Excel格式,便于在电子表格软件中进一步处理:
- # 转换为Excel
- with pd.ExcelWriter('employee_table.xlsx', engine='xlsxwriter') as writer:
- df.to_excel(
- writer,
- sheet_name='员工信息',
- index=False,
- startrow=1, # 从第二行开始写入,留出标题行
- header=False # 不写入列名,因为我们将在下面自定义标题
- )
-
- # 获取工作簿和工作表对象
- workbook = writer.book
- worksheet = writer.sheets['员工信息']
-
- # 添加标题格式
- header_format = workbook.add_format({
- 'bold': True,
- 'text_wrap': True,
- 'valign': 'top',
- 'fg_color': '#D7E4BC',
- 'border': 1
- })
-
- # 写入标题
- for col_num, value in enumerate(df.columns.values):
- worksheet.write(0, col_num, value, header_format)
-
- # 设置列宽
- worksheet.set_column('A:D', 15)
-
- # 添加表格样式
- (max_row, max_col) = df.shape
- worksheet.add_table(
- 0, 0, max_row, max_col - 1,
- {
- 'columns': [{'header': column} for column in df.columns],
- 'style': 'Table Style Medium 9'
- }
- )
-
- # 添加条件格式
- worksheet.conditional_format(
- 1, 3, max_row, 3, # D列(薪资)
- {
- 'type': 'data_bar',
- 'bar_color': '#63C384'
- }
- )
复制代码
可视化输出
结合matplotlib/seaborn
将表格与可视化图表结合,提供更直观的数据展示:
- import matplotlib.pyplot as plt
- import seaborn as sns
- # 设置中文字体
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
- plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
- # 创建图表
- fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
- # 部门人数分布
- dept_counts = df['部门'].value_counts()
- ax1.pie(dept_counts, labels=dept_counts.index, autopct='%1.1f%%', startangle=90)
- ax1.set_title('部门人数分布')
- # 薪资分布
- sns.barplot(x='姓名', y='薪资', data=df, ax=ax2)
- ax2.set_title('员工薪资分布')
- ax2.set_xlabel('姓名')
- ax2.set_ylabel('薪资')
- plt.tight_layout()
- plt.savefig('employee_visualization.png', dpi=300, bbox_inches='tight')
- plt.show()
- # 将表格和图表结合输出
- fig, ax = plt.subplots(figsize=(10, 4))
- ax.axis('tight')
- ax.axis('off')
- # 创建表格
- table = ax.table(
- cellText=df.values,
- colLabels=df.columns,
- cellLoc='center',
- loc='center'
- )
- # 设置表格样式
- table.auto_set_font_size(False)
- table.set_fontsize(10)
- table.scale(1.2, 1.5)
- # 高亮薪资列
- for i in range(len(df)):
- if df.iloc[i]['薪资'] > 15000:
- table[(i+1, 3)].set_facecolor('#ffcccc')
- elif df.iloc[i]['薪资'] < 10000:
- table[(i+1, 3)].set_facecolor('#ccffcc')
- plt.title('员工信息表', fontsize=14, fontweight='bold')
- plt.savefig('employee_table_visualization.png', dpi=300, bbox_inches='tight')
- plt.show()
复制代码
交互式表格输出
使用第三方库创建交互式表格,提升用户体验:
- # 使用ipywidgets创建交互式表格
- from ipywidgets import interact, Dropdown
- # 创建交互式函数
- @interact
- def show_records_more_than(column=['年龄', '薪资'],
- threshold=(0, 20000, 1000)):
- display(df[df[column] > threshold])
- # 使用qgrid创建交互式表格
- try:
- import qgrid
- qgrid_widget = qgrid.show_grid(df, show_toolbar=True)
- qgrid_widget
- except ImportError:
- print("请先安装qgrid: pip install qgrid")
- # 使用itables创建交互式表格
- try:
- from itables import show
- show(df)
- except ImportError:
- print("请先安装itables: pip install itables")
复制代码
实用案例与最佳实践
大数据集处理技巧
当处理大型数据集时,直接输出整个表格可能不切实际。以下是一些处理大数据集的技巧:
- # 创建大型数据集
- large_df = pd.DataFrame({
- 'ID': range(1, 10001),
- 'Value': np.random.randn(10000),
- 'Category': np.random.choice(['A', 'B', 'C', 'D'], 10000)
- })
- # 1. 使用head()和tail()查看数据的前几行和后几行
- print("前5行数据:")
- print(large_df.head())
- print("\n后5行数据:")
- print(large_df.tail())
- # 2. 使用sample()随机抽样
- print("\n随机抽样10行:")
- print(large_df.sample(10))
- # 3. 分组统计
- print("\n按类别分组统计:")
- print(large_df.groupby('Category').agg({
- 'Value': ['count', 'mean', 'std']
- }))
- # 4. 使用describe()获取描述性统计
- print("\n描述性统计:")
- print(large_df.describe())
- # 5. 设置显示选项以适应大数据集
- pd.set_option('display.max_rows', 20)
- pd.set_option('display.max_columns', 10)
- print("\n设置显示选项后的输出:")
- print(large_df)
复制代码
报表生成自动化
自动化报表生成可以大大提高工作效率:
- # 创建报表生成函数
- def generate_report(data, output_format='html'):
- """生成数据报表
-
- Args:
- data: DataFrame, 输入数据
- output_format: str, 输出格式 ('html', 'excel', 'markdown')
-
- Returns:
- 根据输出格式返回报表或保存文件
- """
- # 计算基本统计信息
- stats = data.describe()
-
- # 按部门分组统计
- dept_stats = data.groupby('部门').agg({
- '年龄': ['mean', 'min', 'max'],
- '薪资': ['mean', 'min', 'max', 'sum']
- })
-
- # 格式化输出
- if output_format == 'html':
- # 创建HTML报表
- html = f"""
- <!DOCTYPE html>
- <html>
- <head>
- <title>员工数据报表</title>
- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
- <style>
- body {{ padding: 20px; }}
- .container {{ max-width: 1200px; margin: 0 auto; }}
- h1, h2 {{ color: #333; margin-top: 30px; }}
- .table {{ margin-top: 20px; }}
- .summary {{ background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 20px; }}
- </style>
- </head>
- <body>
- <div class="container">
- <h1>员工数据报表</h1>
- <p class="text-muted">生成时间: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
-
- <div class="summary">
- <h2>数据概览</h2>
- <p>员工总数: <strong>{len(data)}</strong> 人</p>
- <p>平均年龄: <strong>{data['年龄'].mean():.1f}</strong> 岁</p>
- <p>平均薪资: <strong>{data['薪资'].mean():.2f}</strong> 元</p>
- <p>薪资总额: <strong>{data['薪资'].sum():.2f}</strong> 元</p>
- </div>
-
- <h2>员工详细信息</h2>
- {data.to_html(index=False, classes='table table-striped')}
-
- <h2>基本统计信息</h2>
- {stats.to_html(classes='table table-striped')}
-
- <h2>部门统计信息</h2>
- {dept_stats.to_html(classes='table table-striped')}
- </div>
- </body>
- </html>
- """
-
- # 保存HTML文件
- with open('employee_report.html', 'w', encoding='utf-8') as f:
- f.write(html)
-
- return html
-
- elif output_format == 'excel':
- # 创建Excel报表
- with pd.ExcelWriter('employee_report.xlsx', engine='xlsxwriter') as writer:
- # 写入原始数据
- data.to_excel(writer, sheet_name='员工信息', index=False)
-
- # 写入统计信息
- stats.to_excel(writer, sheet_name='基本统计')
-
- # 写入部门统计
- dept_stats.to_excel(writer, sheet_name='部门统计')
-
- # 获取工作簿对象
- workbook = writer.book
-
- # 添加格式
- header_format = workbook.add_format({
- 'bold': True,
- 'text_wrap': True,
- 'valign': 'top',
- 'fg_color': '#D7E4BC',
- 'border': 1
- })
-
- # 为每个工作表添加格式
- for sheetname in writer.sheets:
- worksheet = writer.sheets[sheetname]
-
- # 设置列宽
- for i, col in enumerate(worksheet.columns):
- max_len = max([len(str(cell.value)) for cell in col])
- worksheet.set_column(i, i, max_len + 2)
-
- return "Excel报表已生成: employee_report.xlsx"
-
- elif output_format == 'markdown':
- # 创建Markdown报表
- md = f"""# 员工数据报表
- 生成时间: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}
- ## 数据概览
- - 员工总数: **{len(data)}** 人
- - 平均年龄: **{data['年龄'].mean():.1f}** 岁
- - 平均薪资: **{data['薪资'].mean():.2f}** 元
- - 薪资总额: **{data['薪资'].sum():.2f}** 元
- ## 员工详细信息
- {data.to_markdown(index=False)}
- ## 基本统计信息
- {stats.to_markdown()}
- ## 部门统计信息
- {dept_stats.to_markdown()}
- """
-
- # 保存Markdown文件
- with open('employee_report.md', 'w', encoding='utf-8') as f:
- f.write(md)
-
- return md
-
- else:
- return "不支持的输出格式"
- # 生成HTML报表
- html_report = generate_report(df, 'html')
- print("HTML报表已生成")
- # 生成Excel报表
- excel_result = generate_report(df, 'excel')
- print(excel_result)
- # 生成Markdown报表
- md_report = generate_report(df, 'markdown')
- print("Markdown报表已生成")
复制代码
职场应用场景
在职场中,专业的数据展示可以显著提升工作效率和竞争力。以下是一些实际应用场景:
- # 创建销售数据
- sales_data = pd.DataFrame({
- '月份': ['1月', '2月', '3月', '4月', '5月', '6月'],
- '销售额': [120000, 135000, 148000, 162000, 155000, 178000],
- '成本': [80000, 85000, 90000, 95000, 98000, 105000],
- '利润': [40000, 50000, 58000, 67000, 57000, 73000]
- })
- # 计算利润率
- sales_data['利润率'] = sales_data['利润'] / sales_data['销售额'] * 100
- # 创建销售分析报告
- def create_sales_report(data):
- # 创建图表
- fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
-
- # 销售额和成本趋势图
- ax1.plot(data['月份'], data['销售额'], 'o-', label='销售额')
- ax1.plot(data['月份'], data['成本'], 's-', label='成本')
- ax1.set_title('销售额与成本趋势')
- ax1.set_ylabel('金额 (元)')
- ax1.legend()
- ax1.grid(True)
-
- # 利润率柱状图
- ax2.bar(data['月份'], data['利润率'], color='green', alpha=0.7)
- ax2.set_title('利润率变化')
- ax2.set_ylabel('利润率 (%)')
- ax2.set_ylim(0, 50)
- ax2.grid(True, axis='y')
-
- plt.tight_layout()
- plt.savefig('sales_analysis.png', dpi=300, bbox_inches='tight')
-
- # 创建HTML报告
- html = f"""
- <!DOCTYPE html>
- <html>
- <head>
- <title>销售数据分析报告</title>
- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
- <style>
- body {{ padding: 20px; }}
- .container {{ max-width: 1000px; margin: 0 auto; }}
- h1, h2 {{ color: #333; margin-top: 30px; }}
- .table {{ margin-top: 20px; }}
- .summary {{ background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 20px; }}
- .chart {{ text-align: center; margin: 30px 0; }}
- .positive {{ color: green; }}
- .negative {{ color: red; }}
- </style>
- </head>
- <body>
- <div class="container">
- <h1>销售数据分析报告</h1>
- <p class="text-muted">生成时间: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
-
- <div class="summary">
- <h2>数据概览</h2>
- <p>总销售额: <strong>{data['销售额'].sum():,.2f}</strong> 元</p>
- <p>总成本: <strong>{data['成本'].sum():,.2f}</strong> 元</p>
- <p>总利润: <strong>{data['利润'].sum():,.2f}</strong> 元</p>
- <p>平均利润率: <strong>{data['利润率'].mean():.2f}%</strong></p>
- <p>最高利润率: <strong>{data['利润率'].max():.2f}%</strong> ({data.loc[data['利润率'].idxmax(), '月份']})</p>
- </div>
-
- <div class="chart">
- <h2>销售趋势分析</h2>
- <img src="sales_analysis.png" alt="销售趋势分析" class="img-fluid">
- </div>
-
- <h2>月度销售数据</h2>
- {data.to_html(index=False, classes='table table-striped')}
-
- <h2>环比分析</h2>
- <table class="table table-striped">
- <thead>
- <tr>
- <th>月份</th>
- <th>销售额环比</th>
- <th>利润环比</th>
- <th>利润率变化</th>
- </tr>
- </thead>
- <tbody>
- """
-
- # 添加环比数据
- for i in range(1, len(data)):
- sales_change = (data.iloc[i]['销售额'] - data.iloc[i-1]['销售额']) / data.iloc[i-1]['销售额'] * 100
- profit_change = (data.iloc[i]['利润'] - data.iloc[i-1]['利润']) / data.iloc[i-1]['利润'] * 100
- margin_change = data.iloc[i]['利润率'] - data.iloc[i-1]['利润率']
-
- html += f"""
- <tr>
- <td>{data.iloc[i]['月份']}</td>
- <td class="{'positive' if sales_change > 0 else 'negative'}">{sales_change:.2f}%</td>
- <td class="{'positive' if profit_change > 0 else 'negative'}">{profit_change:.2f}%</td>
- <td class="{'positive' if margin_change > 0 else 'negative'}">{margin_change:.2f}%</td>
- </tr>
- """
-
- html += """
- </tbody>
- </table>
-
- <h2>分析结论</h2>
- <ul>
- <li>销售额整体呈上升趋势,6月份达到最高点178,000元</li>
- <li>利润率在4月份达到最高点41.36%,之后有所回落</li>
- <li>建议进一步分析5月份利润率下降的原因,并采取措施提升利润率</li>
- </ul>
- </div>
- </body>
- </html>
- """
-
- # 保存HTML文件
- with open('sales_report.html', 'w', encoding='utf-8') as f:
- f.write(html)
-
- return html
- # 生成销售报告
- sales_report = create_sales_report(sales_data)
- print("销售分析报告已生成")
复制代码- # 创建项目数据
- projects_data = pd.DataFrame({
- '项目名称': ['网站重构', '移动应用开发', '数据分析平台', '客户管理系统', '市场推广活动'],
- '负责人': ['张三', '李四', '王五', '赵六', '钱七'],
- '开始日期': ['2023-01-15', '2023-02-01', '2023-03-10', '2023-01-20', '2023-04-01'],
- '计划完成日期': ['2023-04-30', '2023-05-15', '2023-06-30', '2023-03-31', '2023-06-15'],
- '实际完成日期': ['2023-04-25', '2023-05-20', None, '2023-04-05', None],
- '进度(%)': [100, 100, 75, 100, 40],
- '预算(万元)': [15, 25, 30, 20, 10],
- '已花费(万元)': [14.5, 26.2, 22.5, 19.8, 4.2]
- })
- # 转换日期格式
- projects_data['开始日期'] = pd.to_datetime(projects_data['开始日期'])
- projects_data['计划完成日期'] = pd.to_datetime(projects_data['计划完成日期'])
- projects_data['实际完成日期'] = pd.to_datetime(projects_data['实际完成日期'])
- # 计算项目状态
- def get_project_status(row):
- if row['进度(%)'] == 100:
- if pd.isna(row['实际完成日期']):
- return '已完成(未更新)'
- elif row['实际完成日期'] <= row['计划完成日期']:
- return '按时完成'
- else:
- return '延期完成'
- else:
- if pd.Timestamp.now() > row['计划完成日期']:
- return '进行中(已延期)'
- else:
- return '进行中'
- projects_data['状态'] = projects_data.apply(get_project_status, axis=1)
- # 计算预算使用率
- projects_data['预算使用率(%)'] = projects_data['已花费(万元)'] / projects_data['预算(万元)'] * 100
- # 创建项目进度跟踪表
- def create_project_status_report(data):
- # 创建HTML报告
- html = f"""
- <!DOCTYPE html>
- <html>
- <head>
- <title>项目进度跟踪报告</title>
- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
- <style>
- body {{ padding: 20px; }}
- .container {{ max-width: 1200px; margin: 0 auto; }}
- h1, h2 {{ color: #333; margin-top: 30px; }}
- .table {{ margin-top: 20px; }}
- .summary {{ background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin-bottom: 20px; }}
- .status-completed {{ color: green; }}
- .status-delayed {{ color: red; }}
- .status-in-progress {{ color: blue; }}
- .progress-bar-container {{ width: 100%; background-color: #f0f0f0; border-radius: 4px; }}
- .progress-bar {{ height: 20px; border-radius: 4px; background-color: #4CAF50; text-align: center; line-height: 20px; color: white; }}
- .budget-ok {{ color: green; }}
- .budget-warning {{ color: orange; }}
- .budget-over {{ color: red; }}
- </style>
- </head>
- <body>
- <div class="container">
- <h1>项目进度跟踪报告</h1>
- <p class="text-muted">生成时间: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
-
- <div class="summary">
- <h2>项目概览</h2>
- <p>总项目数: <strong>{len(data)}</strong> 个</p>
- <p>已完成项目: <strong>{len(data[data['进度(%)'] == 100])}</strong> 个</p>
- <p>进行中项目: <strong>{len(data[data['进度(%)'] < 100])}</strong> 个</p>
- <p>延期项目: <strong>{len(data[data['状态'].str.contains('延期')])}</strong> 个</p>
- <p>总预算: <strong>{data['预算(万元)'].sum():.1f}</strong> 万元</p>
- <p>已花费: <strong>{data['已花费(万元)'].sum():.1f}</strong> 万元</p>
- <p>预算使用率: <strong>{data['已花费(万元)'].sum() / data['预算(万元)'].sum() * 100:.1f}%</strong></p>
- </div>
-
- <h2>项目进度详情</h2>
- <table class="table table-striped">
- <thead>
- <tr>
- <th>项目名称</th>
- <th>负责人</th>
- <th>开始日期</th>
- <th>计划完成日期</th>
- <th>实际完成日期</th>
- <th>进度</th>
- <th>状态</th>
- <th>预算(万元)</th>
- <th>已花费(万元)</th>
- <th>预算使用率</th>
- </tr>
- </thead>
- <tbody>
- """
-
- # 添加项目数据
- for _, row in data.iterrows():
- # 设置状态样式
- if '完成' in row['状态']:
- status_class = 'status-completed'
- elif '延期' in row['状态']:
- status_class = 'status-delayed'
- else:
- status_class = 'status-in-progress'
-
- # 设置预算使用率样式
- if row['预算使用率(%)'] <= 80:
- budget_class = 'budget-ok'
- elif row['预算使用率(%)'] <= 100:
- budget_class = 'budget-warning'
- else:
- budget_class = 'budget-over'
-
- # 格式化日期
- start_date = row['开始日期'].strftime('%Y-%m-%d')
- planned_date = row['计划完成日期'].strftime('%Y-%m-%d')
- actual_date = row['实际完成日期'].strftime('%Y-%m-%d') if pd.notna(row['实际完成日期']) else '-'
-
- html += f"""
- <tr>
- <td>{row['项目名称']}</td>
- <td>{row['负责人']}</td>
- <td>{start_date}</td>
- <td>{planned_date}</td>
- <td>{actual_date}</td>
- <td>
- <div class="progress-bar-container">
- <div class="progress-bar" style="width: {row['进度(%)']}%">{row['进度(%)']}%</div>
- </div>
- </td>
- <td class="{status_class}">{row['状态']}</td>
- <td>{row['预算(万元)']}</td>
- <td>{row['已花费(万元)']}</td>
- <td class="{budget_class}">{row['预算使用率(%)']:.1f}%</td>
- </tr>
- """
-
- html += """
- </tbody>
- </table>
-
- <h2>项目状态分布</h2>
- <div class="row">
- <div class="col-md-6">
- <canvas id="statusChart"></canvas>
- </div>
- <div class="col-md-6">
- <canvas id="progressChart"></canvas>
- </div>
- </div>
-
- <h2>风险与建议</h2>
- <div class="alert alert-warning">
- <h4>风险提示</h4>
- <ul>
- """
-
- # 添加风险提示
- delayed_projects = data[data['状态'].str.contains('延期')]
- if not delayed_projects.empty:
- for _, project in delayed_projects.iterrows():
- html += f"<li><strong>{project['项目名称']}</strong> 已延期,请关注进度</li>"
-
- over_budget_projects = data[data['预算使用率(%)'] > 100]
- if not over_budget_projects.empty:
- for _, project in over_budget_projects.iterrows():
- html += f"<li><strong>{project['项目名称']}</strong> 已超出预算,当前使用率 {project['预算使用率(%)']:.1f}%</li>"
-
- html += """
- </ul>
- </div>
-
- <div class="alert alert-info">
- <h4>改进建议</h4>
- <ul>
- <li>定期召开项目进度会议,及时发现问题并解决</li>
- <li>对于延期项目,分析原因并调整资源分配</li>
- <li>加强预算控制,避免超支情况发生</li>
- <li>建立项目风险预警机制,提前识别潜在问题</li>
- </ul>
- </div>
- </div>
-
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
- <script>
- // 项目状态分布图
- const statusCtx = document.getElementById('statusChart').getContext('2d');
- const statusChart = new Chart(statusCtx, {
- type: 'pie',
- data: {
- labels: ['按时完成', '延期完成', '进行中', '进行中(已延期)'],
- datasets: [{
- data: [
- """
-
- # 添加状态数据
- status_counts = data['状态'].value_counts()
- html += f"{status_counts.get('按时完成', 0)}, "
- html += f"{status_counts.get('延期完成', 0)}, "
- html += f"{status_counts.get('进行中', 0)}, "
- html += f"{status_counts.get('进行中(已延期)', 0)}"
-
- html += """
- ],
- backgroundColor: [
- '#4CAF50',
- '#F44336',
- '#2196F3',
- '#FF9800'
- ]
- }]
- },
- options: {
- responsive: true,
- plugins: {
- legend: {
- position: 'bottom',
- },
- title: {
- display: true,
- text: '项目状态分布'
- }
- }
- }
- });
-
- // 项目进度图
- const progressCtx = document.getElementById('progressChart').getContext('2d');
- const progressChart = new Chart(progressCtx, {
- type: 'bar',
- data: {
- labels: [
- """
-
- # 添加项目名称
- for project in data['项目名称']:
- html += f"'{project}', "
-
- html = html.rstrip(', ') + """
- ],
- datasets: [{
- label: '进度 (%)',
- data: [
- """
-
- # 添加进度数据
- for progress in data['进度(%)']:
- html += f"{progress}, "
-
- html = html.rstrip(', ') + """
- ],
- backgroundColor: [
- """
-
- # 根据进度设置颜色
- for progress in data['进度(%)']:
- if progress == 100:
- html += "'#4CAF50', "
- elif progress >= 80:
- html += "'#8BC34A', "
- elif progress >= 50:
- html += "'#FFC107', "
- else:
- html += "'#F44336', "
-
- html = html.rstrip(', ') + """
- ]
- }]
- },
- options: {
- responsive: true,
- plugins: {
- legend: {
- display: false
- },
- title: {
- display: true,
- text: '项目进度'
- }
- },
- scales: {
- y: {
- beginAtZero: true,
- max: 100,
- title: {
- display: true,
- text: '进度 (%)'
- }
- }
- }
- }
- });
- </script>
- </body>
- </html>
- """
-
- # 保存HTML文件
- with open('project_status_report.html', 'w', encoding='utf-8') as f:
- f.write(html)
-
- return html
- # 生成项目进度报告
- project_report = create_project_status_report(projects_data)
- print("项目进度跟踪报告已生成")
复制代码
总结与展望
本文深入探索了pandas表格输出的多种方法与实用技巧,从基础的print()函数到高级的样式设置和交互式表格,涵盖了数据展示的各个方面。通过这些技巧,我们可以让数据分析结果更加专业直观,提升工作效率和职场竞争力。
在实际应用中,选择合适的表格输出方法取决于具体场景和需求。对于简单的数据查看,基础的输出方法就足够了;而对于正式的报告和展示,则需要更加精美的格式和样式。自动化报表生成可以大大提高工作效率,特别是在需要定期生成相似报告的场景中。
随着数据分析和可视化技术的不断发展,pandas的表格输出功能也在不断丰富和完善。未来,我们可以期待更多交互式、动态化的表格输出方式,以及与其他数据可视化工具的更紧密集成。
掌握pandas表格输出的多种方法与技巧,不仅能够解决数据展示难题,还能在职场中展现专业能力,提升个人竞争力。希望本文的内容能够帮助读者更好地利用pandas进行数据展示,为数据分析和决策提供更有力的支持。 |
|