pandas 数据处理案例

本篇实现一个 pandas 综合数据处理的案例。假设的场景就是计算某期间的物料进出存,涉及 pandas 多个 data frame 的关联、日期类型数据信息的提取、数据分组汇总等,掌握后应该能应付日常很多数据处理场景。这个案例之前我利用 MS Access 和 Power Query 都进行过加工操作,并发过了博文讲解数据处理过程,有兴趣的朋友可以在我之前的博客中查看。本次来看看 利用 pandas 如何进行数据处理。数据存放在 SQL Server Express 数据库中,主要表的结构和表之间的关系如下:


示例数据在 github 上有 Access 版本的数据可供下载,在文章的最后给出连接地址。

python 读取 Sql Server

对数据库的连接和读取,利用 sqlalchemy + pyodbc。在 Windows 上,使用 odbcad32 命令创建 odbc 连接的数据源:

首先选择驱动程序:


然后指定数据源名称和连接的服务器

选择验证方式:

选择默认连接的数据库:


其他使用默认选项,一路下一步直到完成。

进行了 odbc 配置之后,在 python 中使用 sqlalchemy + pyodbc 通过下面的方法建立与 sql server 数据库的连接 (建立 engine ):

from sqlalchemy import create_engine
engine = create_engine('mssql+pyodbc://username:pwd!@mssql')

这里的 mssql 就是上面 odbc 数据源配置的 DSN (data source name)。username 和 password 按数据库登录密码。

然后使用 sql 语句建立 3 个 data frame:

df_details = pd.read_sql(
    'select DocNo, MaterialNo, Qty from dbo.stock_movement_details',  engine)

df_headers = pd.read_sql(
    'select DocNo, DocDate, MovementType from dbo.stock_movement_headers',  engine)

df_mvt_type = pd.read_sql(
    'select MovementTypeID, InoutSign from dbo.movement_types', engine)

通过两次 merge 将三个 data frame 组合在一起:

df_merged_headers = df_details.merge(df_headers, on='DocNo')
df = df_merged_headers.merge(
    df_mvt_type, left_on='MovementType', right_on='MovementTypeID')

然后添加字段,使用的就是条件列方法。条件列在表达或者条件的时候,需要用 np.where() 的嵌套方式来实现:

df['TxYear'] = df.DocDate.dt.year
df['TxMonth'] = df.DocDate.dt.month

df['ActualQty'] = np.where(
    df.InoutSign == "+",
    df.Qty,
    -1 * df.Qty
)

df['BeginQty'] = np.where(
    df.TxYear < year,
    df.ActualQty,
    (np.where(
        (df.TxYear == year) & (df.TxMonth < month),
        df.ActualQty,
        0
    ))
)

df['StockIn'] = np.where(
    (df.TxYear == year) & (df.TxMonth == month) & (df.InoutSign == "+"),
    df.ActualQty,
    0
)

df['StockOut'] = np.where(
    (df.TxYear == year) & (df.TxMonth == month) & (df.InoutSign == "-"),
    df.ActualQty,
    0
)

df['EndQty'] = df.BeginQty + df.StockIn + df.StockOut

最后使用分组汇总得到结果:

df_grouped = df[['MaterialNo', 'BeginQty', 'StockIn',
                 'StockOut', 'EndQty']].groupby('MaterialNo').sum()

利用 xlwings 在 VBA 中调用 python

xlwings 的基本使用方法,请参考我下面的这篇文章

xlwings : 从此可以 VBA 调用 Python 代码啦

本次使用 Excel 作界面,将查询条件在 Excel 单元格中输入,然后将参数传递给 python,调用 python 代码获取计算结果 (结果的数据类型为 pandas dataframe), 然后用 xlwings 库将数据写入 Excel 工作表。

Excel 筛选条件的界面如下:

点击 Refresh 按钮,调用下面的 VBA 代码:

Public Sub GetStockBalances()
    Dim mymodule As String
    mymodule = "stockbalances"
        
    Dim txYear As String
    Dim txMonth As String
    txYear = Sheet3.Range("B1").Value
    txMonth = Sheet3.Range("B2").Value
    
    ' clear Sheet1 content
    Sheet1.Cells.ClearContents
    
    Dim parms As String
    parms = "('" & txYear & "','" & txMonth & "')"
    
    RunPython ("import " & mymodule & ";" & mymodule & ".get_stock_balances" & parms)
End Sub

参数 从 VBA 传递给 python,使用 String 类型,所以在每个参数的两边加上单引号 (’)

示例数据和代码

github : pandas-xlwings-stock-balances

发布了188 篇原创文章 · 获赞 136 · 访问量 43万+

猜你喜欢

转载自blog.csdn.net/stone0823/article/details/101783657