Julia中高效计算多列百分比变化的方法
Julia DataFrame 批量分组计算多列百分比变化
给定如下示例DataFrame,需要按id分组,计算每组内指定列(实际场景有50列)的百分比变化:
using DataFrames, Dates # 示例数据 df = DataFrame( id = [1, 1, 2, 2, 3, 3], filing_date = Date.(["2022-01-01", "2022-02-01", "2022-01-10", "2022-02-20", "2022-01-15", "2022-03-01"]), col1 = [100, 110, 200, 220, 50, 55], col2 = [1000, 1050, 2000, 2100, 500, 525] )
原方案仅支持单列处理,需合并多个结果表,效率低下。以下是两种高效的批量处理方案:
方案一:自定义批量处理函数 + 单次分组计算
直接定义可处理多列的分组函数,一次性完成所有列的计算,避免多次分组和合并操作:
# 定义批量计算百分比变化的函数 function percent_change_group(gdf::SubDataFrame, target_cols::Vector{Symbol}) sort!(gdf, :filing_date, rev=true) if nrow(gdf) < 2 # 组内不足两行时,所有列返回missing return DataFrame([Symbol(col, "_change") => [missing] for col in target_cols]) end # 计算每列的百分比变化 changes = [(gdf[1, col] - gdf[2, col]) / gdf[2, col] * 100 for col in target_cols] return DataFrame([Symbol(col, "_change") => [val] for (col, val) in zip(target_cols, changes)]) end # 指定需要处理的列(排除id和filing_date) target_cols = setdiff(names(df), [:id, :filing_date]) # 分组计算并生成结果 result = combine(groupby(df, :id), gdf -> percent_change_group(gdf, target_cols))
方案二:transform + lag 链式处理
利用lag函数获取每组内的前一行数据,结合分组过滤得到最终结果,逻辑更直观:
# 指定目标列 target_cols = setdiff(names(df), [:id, :filing_date]) # 链式操作完成排序、滞后值计算、变化率计算 using DataFramesMeta result = @chain df begin groupby(:id) @transform begin # 每组内按filing_date降序排序 sort!(:filing_date, rev=true) # 为每个目标列生成滞后值(前一行数据) $(Symbol.(target_cols, "_prev")) = lag.(cols(target_cols), 1) end groupby(:id) @combine begin if nrow(_) < 2 # 组内不足两行时返回missing $(Symbol.(target_cols, "_change")) .= missing else # 计算百分比变化 $(Symbol.(target_cols, "_change")) = (cols(target_cols)[1] .- cols(Symbol.(target_cols, "_prev"))[1]) ./ cols(Symbol.(target_cols, "_prev"))[1] .* 100 end end end
验证结果
两种方案均会生成符合预期的结果:
Row │ id col1_change col2_change │ Int64 Float64? Float64? ─────┼────────────────────────────────── 1 │ 1 10.0 5.0 2 │ 2 10.0 5.0 3 │ 3 10.0 5.0
内容的提问来源于stack exchange,提问作者IsThere
相关产品推荐
相关产品推荐

