跳转到主要内容

pandas && 强大的数据操作处理程序

安装


pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple

# excel支持
pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install xlsxwriter  -i https://pypi.tuna.tsinghua.edu.cn/simple

连接到数据

支持读取多张数据:CSV,JSON,Excel,mysql等。

具体可以参考:https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html

api设计的非常简洁:

  • 读取:read_csv , read_json , read_excel,read_sql
  • 写入:to_csv , to_json,to_excel , to_sql
连接到mysql

pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple 



# 增加pandas库的导入
import pandas as pd

# 添加SQLAlchemy的导入
from sqlalchemy import create_engine

# 示例用法
if True:
    engine = create_engine(
        "mysql+pymysql://root:password@192.168.0.10:33318/renren_cloud_basic"
    )
    query = "SELECT * FROM park_user"
    # 使用chunksize参数来实现流式处理
    df = pd.read_sql(query, engine)
    # 显示数据的结构和数据类型
    print(df.info())
    # 显示列名
    print(df.columns)



连接到mysql的额外操作
  • read_sql_table(table_name,connection)
  • read_sql_query(sql,connection)
  • read_sql(sql,connection)

操作数据

  • 获取数据形状

row_size, col_size = grouped.shape
log.info(f"row_size:{row_size},col_size:{col_size}")

# row_size:13,col_size:7
  • 数据清洗:提取数据到新的列

# 将月份列提取为年
dataFrame["年份"] = pd.to_datetime(dataFrame["月份"]).dt.year

  • 数据清洗:清洗空值

  • 数据清洗:清洗格式错误数据

  • 数据清洗:清洗错误数据

  • 数据清洗:清洗重复数据

  • 分组聚合


grouped = (
    dataFrame.groupby(["客户名称", "合同编号", "年份"])
    .agg(
        {
            "减免总金额": "sum",
            "政策减免金额": "sum",
            "运营减免金额": "sum",
            "其他减免金额": "sum",
        }
    )
    .reset_index()  # 使分组变成一个平面
)

# 设置索引列的名称为“序号”
grouped.index.name = "序号"

  • 筛选数据

# 提取整列数据
print(grouped["客户名称"])


# 筛选客户名称列数据
print(grouped[grouped["客户名称"] == "山东智拓大数据有限公司"])

写入Eexcel时设置样式

pandas是做数据处理的,默认导出并不能设置样式、合并单元格等,需要记住其他工具。


# 自定义写入程序,使用xlsxwriter写入
with pd.ExcelWriter("./files/output.xlsx", engine="xlsxwriter") as writer:

    # 直接写入数据,没有样式
    # grouped.to_excel(writer, sheet_name="Sheet1", startrow=1, startcol=1, index=True)

    # 获取工作表
    workbook = writer.book
    worksheet = None
    # 如果worksheet不存在,则创建一个工作表
    if "Sheet1" in writer.sheets:
        worksheet = writer.sheets["Sheet1"]
    else:
        worksheet = workbook.add_worksheet("Sheet1")

    # 创建样式
    default_format = {
        "bold": False,
        # 边框
        "border": 1,
        # 垂直居中
        "valign": "vcenter",
        # 自动换行
        "text_wrap": True,
        # 水平居中
        # "align": "center",
        # 字体大小
        "font_size": 9,
    }

    # 创建样式
    cell_format_default = workbook.add_format(default_format)
    cell_format_head = workbook.add_format(
        {
            **default_format,
            **{
                "align": "center",
                "bold": True,
            },
        }
    )

    # 设置列的宽度,单位是多少个字符,一个中文占两个字符
    worksheet.set_column("A:A", 10)
    worksheet.set_column("B:B", 30)
    worksheet.set_column("C:C", 20)
    worksheet.set_column("E:H", 12)

    # 插入logo图片
    worksheet.insert_image(
        "A1",
        "./files/logo.png",
        {
            "x_scale": first_row_height / logo_image_height,
            "y_scale": first_row_height / logo_image_height,
            "x_offset": 5,
            "y_offset": 5,
        },
    )
    # 合并单元格
    worksheet.merge_range("A1:B1", "", cell_format_head)
    worksheet.merge_range("C1:H1", "租金减免表", cell_format_head)
    # 设置行高,单位是像素
    worksheet.set_row(0, first_row_height)

    # 增加序号列
    worksheet.write("A2", "序号", cell_format_head)
    worksheet.write_column("A3", range(1, len(grouped) + 1), cell_format_head)

    # 计算行和列的偏移量
    row_offset = 2
    col_offset = 1

    # 写入数据并设置样式,使用xlsxwriter作为驱动引擎时,需要将数据与样式一起写入,并不能直接修改样式
    for row_num, row_data in grouped.iterrows():
        for col_num, col_data in enumerate(row_data):
            worksheet.write(
                row_num + row_offset,
                col_num + col_offset,
                col_data,
                cell_format_default,
            )

    # 合并合同编号列,如果连续的行数据相同,则合并
    start_row = 0
    for row_num, row_data in grouped.iterrows():
        current_value = row_data["合同编号"]
        next_row = row_num + 1
        next_value = (
            grouped.iloc[next_row]["合同编号"] if next_row < len(grouped) else None
        )
        if current_value != next_value:
            log.info(f"{start_row} - {row_num} - {current_value}")
            if row_num - start_row > 0:
                worksheet.merge_range(
                    start_row + row_offset,
                    grouped.columns.get_loc("合同编号") + col_offset,
                    row_num + row_offset,
                    grouped.columns.get_loc("合同编号") + col_offset,
                    current_value,
                    cell_format_default,
                )
            start_row = next_row