`Python`的`Excel`操作:`pandas`和`openpyxl`的`高级`用法。

Python Excel 操作:Pandas 与 Openpyxl 高级用法

大家好,今天我们来深入探讨 Python 中使用 Pandas 和 Openpyxl 操作 Excel 的高级技巧。Excel 作为数据处理和报告生成的常用工具,掌握高效的 Python 操作方法至关重要。我们将结合实际案例,讲解如何利用这两个库提升数据处理和报告生成效率。

一、 Pandas 高级用法

Pandas 提供了强大的数据分析和处理能力,与 Excel 的交互也非常便捷。以下是一些 Pandas 的高级用法,能够更高效地处理 Excel 数据。

1. 多 Sheet 读取与写入

通常一个 Excel 文件包含多个 Sheet,我们需要能够方便地读取和写入多个 Sheet。

  • 读取多个 Sheet:

    使用 pd.ExcelFile 对象可以一次性读取 Excel 文件中的所有 Sheet,然后按 Sheet 名称或索引访问。

    import pandas as pd
    
    excel_file = pd.ExcelFile('multi_sheet.xlsx')
    
    # 获取所有 sheet 名称
    sheet_names = excel_file.sheet_names
    print(f"Sheet names: {sheet_names}")
    
    # 按 sheet 名称读取
    df_sheet1 = excel_file.parse('Sheet1')
    df_sheet2 = excel_file.parse('Sheet2') # 或者 excel_file.parse(0) 用 index 读取
    
    print("Sheet1 data:")
    print(df_sheet1.head())
    print("Sheet2 data:")
    print(df_sheet2.head())
  • 写入多个 Sheet:

    使用 ExcelWriter 对象可以同时写入多个 DataFrame 到不同的 Sheet。

    import pandas as pd
    
    df1 = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})
    df2 = pd.DataFrame({'colA': ['a', 'b'], 'colB': ['c', 'd']})
    
    with pd.ExcelWriter('multi_sheet_output.xlsx') as writer:
        df1.to_excel(writer, sheet_name='Sheet1', index=False)
        df2.to_excel(writer, sheet_name='Sheet2', index=False)
    
    print("Multi-sheet Excel file created successfully!")

2. 数据清洗与转换

Pandas 提供了丰富的数据清洗和转换功能,可以在读取 Excel 数据后进行预处理,例如处理缺失值、转换数据类型、去除重复项等。

  • 处理缺失值:

    import pandas as pd
    import numpy as np
    
    # 创建包含缺失值的 DataFrame
    data = {'col1': [1, 2, np.nan, 4], 'col2': [5, np.nan, 7, 8]}
    df = pd.DataFrame(data)
    print("Original DataFrame:")
    print(df)
    
    # 填充缺失值
    df_filled = df.fillna(0) # 用 0 填充
    print("nDataFrame after filling NaN with 0:")
    print(df_filled)
    
    df_filled_mean = df.fillna(df.mean()) # 用均值填充
    print("nDataFrame after filling NaN with mean:")
    print(df_filled_mean)
    
    # 删除包含缺失值的行
    df_dropna = df.dropna()
    print("nDataFrame after dropping rows with NaN:")
    print(df_dropna)
  • 数据类型转换:

    import pandas as pd
    
    # 创建 DataFrame
    data = {'col1': ['1', '2', '3'], 'col2': ['4.5', '5.6', '6.7']}
    df = pd.DataFrame(data)
    print("Original DataFrame:")
    print(df.dtypes)
    print(df)
    
    # 转换数据类型
    df['col1'] = pd.to_numeric(df['col1'])
    df['col2'] = pd.to_numeric(df['col2'])
    print("nDataFrame after converting data types:")
    print(df.dtypes)
    print(df)
  • 去除重复项:

    import pandas as pd
    
    # 创建包含重复项的 DataFrame
    data = {'col1': [1, 2, 2, 3], 'col2': ['a', 'b', 'b', 'c']}
    df = pd.DataFrame(data)
    print("Original DataFrame:")
    print(df)
    
    # 去除重复项
    df_deduplicated = df.drop_duplicates()
    print("nDataFrame after removing duplicates:")
    print(df_deduplicated)
    
    # 基于特定列去除重复项
    df_deduplicated_col1 = df.drop_duplicates(subset=['col1'])
    print("nDataFrame after removing duplicates based on 'col1':")
    print(df_deduplicated_col1)

3. 数据筛选与排序

Pandas 提供了灵活的数据筛选和排序功能,可以根据条件提取数据,并按指定列进行排序。

  • 数据筛选:

    import pandas as pd
    
    # 创建 DataFrame
    data = {'col1': [1, 2, 3, 4, 5], 'col2': ['a', 'b', 'c', 'b', 'a']}
    df = pd.DataFrame(data)
    print("Original DataFrame:")
    print(df)
    
    # 根据条件筛选数据
    df_filtered = df[df['col1'] > 2]
    print("nDataFrame after filtering 'col1' > 2:")
    print(df_filtered)
    
    df_filtered_multiple = df[(df['col1'] > 2) & (df['col2'] == 'b')]
    print("nDataFrame after filtering 'col1' > 2 and 'col2' == 'b':")
    print(df_filtered_multiple)
    
    df_filtered_isin = df[df['col2'].isin(['a', 'c'])]
    print("nDataFrame after filtering 'col2' in ['a', 'c']:")
    print(df_filtered_isin)
  • 数据排序:

    import pandas as pd
    
    # 创建 DataFrame
    data = {'col1': [3, 1, 4, 2, 5], 'col2': ['c', 'a', 'd', 'b', 'e']}
    df = pd.DataFrame(data)
    print("Original DataFrame:")
    print(df)
    
    # 按单列排序
    df_sorted = df.sort_values(by='col1')
    print("nDataFrame after sorting by 'col1':")
    print(df_sorted)
    
    # 按多列排序
    df_sorted_multiple = df.sort_values(by=['col2', 'col1'])
    print("nDataFrame after sorting by 'col2' then 'col1':")
    print(df_sorted_multiple)
    
    # 降序排序
    df_sorted_descending = df.sort_values(by='col1', ascending=False)
    print("nDataFrame after sorting by 'col1' in descending order:")
    print(df_sorted_descending)

4. 数据分组与聚合

Pandas 提供了强大的数据分组和聚合功能,可以根据指定列对数据进行分组,并进行统计分析。

import pandas as pd

# 创建 DataFrame
data = {'Category': ['A', 'A', 'B', 'B', 'A', 'C', 'C'],
        'Value': [10, 15, 20, 25, 12, 30, 35]}
df = pd.DataFrame(data)
print("Original DataFrame:")
print(df)

# 数据分组与聚合
grouped = df.groupby('Category')['Value'].sum()
print("nGrouped data (sum of 'Value' by 'Category'):")
print(grouped)

grouped_multiple = df.groupby('Category')['Value'].agg(['sum', 'mean', 'count'])
print("nGrouped data (sum, mean, count of 'Value' by 'Category'):")
print(grouped_multiple)

grouped_apply = df.groupby('Category')['Value'].apply(lambda x: x / x.sum()) # 计算每个 category 内 value 的占比
print("nGrouped data (Value percentage within each Category):")
print(grouped_apply)

5. 使用 pd.read_excelconverters 参数进行复杂数据类型处理

pd.read_excelconverters 参数允许我们在读取 Excel 时,对特定列应用自定义函数进行数据类型转换或数据清洗。

import pandas as pd

def clean_phone_number(phone_number):
    """清理电话号码,移除非数字字符并确保格式正确"""
    if isinstance(phone_number, str):
        cleaned_number = ''.join(filter(str.isdigit, phone_number))
        if len(cleaned_number) == 11 and cleaned_number.startswith('86'):  # 假设中国号码
            return cleaned_number[2:]  # 去除前缀 86
        elif len(cleaned_number) == 10: # 假设美国号码
            return cleaned_number
        else:
            return None # 无效号码
    else:
        return None # 非字符串类型,返回None

# 创建包含需要清洗的电话号码的 Excel 文件
data = {'Name': ['Alice', 'Bob', 'Charlie'],
        'Phone': ['86-13800000000', '123-456-7890', 'invalid']}
df = pd.DataFrame(data)
df.to_excel('phone_numbers.xlsx', index=False)

# 使用 converters 参数读取 Excel 文件并清洗电话号码
df_cleaned = pd.read_excel('phone_numbers.xlsx', converters={'Phone': clean_phone_number})

print(df_cleaned)

二、 Openpyxl 高级用法

Openpyxl 提供了更底层的 Excel 操作能力,可以精细控制 Excel 文件的格式、样式和公式。以下是一些 Openpyxl 的高级用法。

1. 创建 Excel 文件并写入数据

from openpyxl import Workbook

# 创建新的 Workbook 对象
workbook = Workbook()

# 获取当前活跃的 Sheet
sheet = workbook.active

# 写入数据
sheet['A1'] = 'Hello'
sheet['B1'] = 'World'

# 写入多行数据
data = [
    ['Name', 'Age', 'City'],
    ['Alice', 30, 'New York'],
    ['Bob', 25, 'London'],
    ['Charlie', 35, 'Paris']
]

for row_idx, row_data in enumerate(data):
    for col_idx, cell_value in enumerate(row_data):
        sheet.cell(row=row_idx + 1, column=col_idx + 1, value=cell_value)

# 保存 Excel 文件
workbook.save('example.xlsx')

print("Excel file created successfully!")

2. 读取 Excel 文件数据

from openpyxl import load_workbook

# 加载 Excel 文件
workbook = load_workbook('example.xlsx')

# 获取 Sheet
sheet = workbook['Sheet'] # 或者 workbook.active

# 读取单元格数据
cell_value = sheet['A1'].value
print(f"Value of A1: {cell_value}")

# 遍历所有行
for row in sheet.iter_rows(min_row=1, max_row=sheet.max_row, min_col=1, max_col=sheet.max_column, values_only=True):
    print(row)

# 遍历特定列
for cell in sheet['A']:
    print(cell.value)

3. 格式化单元格样式

Openpyxl 允许我们自定义单元格的字体、颜色、对齐方式等样式。

from openpyxl import Workbook
from openpyxl.styles import Font, Color, Alignment, PatternFill

# 创建 Workbook
workbook = Workbook()
sheet = workbook.active

# 设置字体样式
font = Font(name='Arial', size=12, bold=True, italic=True, color='FF0000')
sheet['A1'].font = font
sheet['A1'] = 'Formatted Text'

# 设置对齐方式
alignment = Alignment(horizontal='center', vertical='center')
sheet['B1'].alignment = alignment
sheet['B1'] = 'Aligned Text'

# 设置背景颜色
fill = PatternFill(start_color='FFFF00', end_color='FFFF00', fill_type='solid')
sheet['C1'].fill = fill
sheet['C1'] = 'Colored Background'

# 设置行高和列宽
sheet.row_dimensions[1].height = 30
sheet.column_dimensions['A'].width = 20

workbook.save('formatted.xlsx')
print("Excel file with formatting created successfully!")

4. 添加公式

Openpyxl 支持在单元格中添加 Excel 公式,并自动计算结果。

from openpyxl import Workbook

# 创建 Workbook
workbook = Workbook()
sheet = workbook.active

# 写入数据
sheet['A1'] = 10
sheet['A2'] = 20

# 添加公式
sheet['A3'] = '=SUM(A1:A2)'  # 计算 A1 和 A2 的和

# 保存 Excel 文件
workbook.save('formula.xlsx')
print("Excel file with formula created successfully!")

5. 插入图表

Openpyxl 允许我们在 Excel 中插入各种类型的图表,例如柱状图、折线图、饼图等。

from openpyxl import Workbook
from openpyxl.chart import BarChart, Reference

# 创建 Workbook
workbook = Workbook()
sheet = workbook.active

# 写入数据
data = [
    ['Category', 'Value'],
    ['A', 10],
    ['B', 40],
    ['C', 50],
    ['D', 30]
]

for row_idx, row_data in enumerate(data):
    for col_idx, cell_value in enumerate(row_data):
        sheet.cell(row=row_idx + 1, column=col_idx + 1, value=cell_value)

# 创建柱状图
chart = BarChart()
chart.title = 'Bar Chart Example'
chart.x_axis.title = 'Category'
chart.y_axis.title = 'Value'

# 定义数据范围
data_values = Reference(sheet, min_col=2, min_row=2, max_col=2, max_row=5)
categories = Reference(sheet, min_col=1, min_row=2, max_col=1, max_row=5)

# 添加数据
chart.add_data(data_values, titles_from_data=True)
chart.set_categories(categories)

# 将图表添加到 Sheet
sheet.add_chart(chart, 'E2')

# 保存 Excel 文件
workbook.save('chart.xlsx')
print("Excel file with chart created successfully!")

6. 合并单元格

from openpyxl import Workbook

workbook = Workbook()
sheet = workbook.active

sheet.merge_cells('A1:B2')
sheet['A1'] = "Merged Cell"

workbook.save('merged_cells.xlsx')
print("Excel file with merged cells created successfully!")

7. 使用 Openpyxl 调整列宽以适应内容

Openpyxl 本身没有直接提供自动调整列宽以适应内容的功能,但我们可以通过计算单元格中最长内容的长度来手动调整列宽。

from openpyxl import Workbook
from openpyxl.utils import get_column_letter

def adjust_column_width(sheet):
    for col in sheet.columns:
        max_length = 0
        column = col[0].column_letter  # 获取列的字母标识

        for cell in col:
            try:  # 单元格可能包含公式,图片等,需要 try except
                if len(str(cell.value)) > max_length:
                    max_length = len(str(cell.value))
            except:
                pass

        adjusted_width = (max_length + 2)  # 添加一些额外的空间
        sheet.column_dimensions[column].width = adjusted_width

# 创建 Workbook
workbook = Workbook()
sheet = workbook.active

# 写入数据
data = [
    ['Product', 'Description', 'Price'],
    ['Laptop', 'A high-performance laptop with a 15-inch display and a powerful processor', 1200],
    ['Smartphone', 'A cutting-edge smartphone with a stunning camera and long battery life', 800],
    ['Tablet', 'A versatile tablet for work and entertainment', 300]
]

for row_idx, row_data in enumerate(data):
    for col_idx, cell_value in enumerate(row_data):
        sheet.cell(row=row_idx + 1, column=col_idx + 1, value=cell_value)

# 调整列宽
adjust_column_width(sheet)

# 保存 Excel 文件
workbook.save('adjusted_column_width.xlsx')
print("Excel file with adjusted column width created successfully!")

三、 Pandas 与 Openpyxl 结合使用

Pandas 擅长数据处理,Openpyxl 擅长格式控制。我们可以将两者结合起来,先使用 Pandas 处理数据,然后使用 Openpyxl 对 Excel 文件进行格式化。

import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, Alignment

# 1. 使用 Pandas 读取 Excel 数据
df = pd.DataFrame({'col1': [1, 2, 3], 'col2': ['a', 'b', 'c']})
excel_file = 'combined.xlsx'
with pd.ExcelWriter(excel_file, engine='openpyxl') as writer:
    df.to_excel(writer, sheet_name='Sheet1', index=False)

# 2. 使用 Openpyxl 加载 Excel 文件
workbook = load_workbook(excel_file)
sheet = workbook['Sheet1']

# 3. 格式化表头
header_font = Font(bold=True, color='0000FF')
header_alignment = Alignment(horizontal='center')

for cell in sheet[1]: # 第一行是表头
    cell.font = header_font
    cell.alignment = header_alignment

# 保存 Excel 文件
workbook.save(excel_file)
print("Combined Pandas and Openpyxl example completed successfully!")

在这个例子中,我们首先使用 Pandas 创建一个 DataFrame,并将其写入 Excel 文件。然后,使用 Openpyxl 加载 Excel 文件,并对表头进行格式化,例如设置为粗体、蓝色字体和居中对齐。

四、 实际案例:生成销售报告

假设我们需要根据销售数据生成一份 Excel 报告,包含以下内容:

  • 总销售额
  • 按产品类别统计销售额
  • 按销售区域统计销售额
  • 绘制销售额柱状图

首先,我们准备一份包含销售数据的 Excel 文件 sales_data.xlsx,包含以下列:Product, Category, Region, Sales

然后,我们可以使用 Pandas 和 Openpyxl 结合来实现报告生成。

import pandas as pd
from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.chart import BarChart, Reference
from openpyxl.styles import Font, Alignment

# 1. 读取销售数据
sales_data = pd.read_excel('sales_data.xlsx')

# 2. 计算总销售额
total_sales = sales_data['Sales'].sum()

# 3. 按产品类别统计销售额
category_sales = sales_data.groupby('Category')['Sales'].sum().reset_index()

# 4. 按销售区域统计销售额
region_sales = sales_data.groupby('Region')['Sales'].sum().reset_index()

# 5. 创建 Excel 文件
report_file = 'sales_report.xlsx'
with pd.ExcelWriter(report_file, engine='openpyxl') as writer:
    # 写入总销售额
    total_sales_df = pd.DataFrame({'Metric': ['Total Sales'], 'Value': [total_sales]})
    total_sales_df.to_excel(writer, sheet_name='Summary', index=False, startrow=0, startcol=0)

    # 写入按产品类别统计
    category_sales.to_excel(writer, sheet_name='Category Sales', index=False)

    # 写入按销售区域统计
    region_sales.to_excel(writer, sheet_name='Region Sales', index=False)

# 6. 使用 Openpyxl 格式化 Excel 文件
workbook = load_workbook(report_file)

# 格式化 Summary sheet
summary_sheet = workbook['Summary']
summary_sheet['A1'].font = Font(bold=True)
summary_sheet['B1'].font = Font(bold=True)
summary_sheet['A1'].alignment = Alignment(horizontal='center')
summary_sheet['B1'].alignment = Alignment(horizontal='center')

# 绘制 Category Sales 柱状图
category_sheet = workbook['Category Sales']
chart = BarChart()
chart.title = 'Category Sales Chart'
chart.x_axis.title = 'Category'
chart.y_axis.title = 'Sales'

data = Reference(category_sheet, min_col=2, min_row=1, max_col=2, max_row=category_sheet.max_row)
categories = Reference(category_sheet, min_col=1, min_row=2, max_col=1, max_row=category_sheet.max_row)

chart.add_data(data, titles_from_data=True)
chart.set_categories(categories)

category_sheet.add_chart(chart, 'D2')

# 保存 Excel 文件
workbook.save(report_file)
print("Sales report generated successfully!")

这个案例展示了如何使用 Pandas 进行数据处理和分析,然后使用 Openpyxl 对 Excel 文件进行格式化和添加图表,最终生成一份完整的销售报告。

总结

掌握 Pandas 和 Openpyxl 的高级用法,能够极大地提升 Python 在 Excel 数据处理和报告生成方面的效率。Pandas 擅长数据清洗、转换、筛选、排序和聚合,而 Openpyxl 擅长 Excel 文件的格式化、公式添加和图表插入。结合使用这两个库,可以实现复杂且精美的 Excel 报告生成。

进一步提升的方向

  • 错误处理和日志记录
  • 性能优化(例如使用 openpyxl.cell.read_only=True 读取大型 Excel 文件)
  • 更复杂的图表定制
  • 自动化报告生成流程(例如定时任务)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注