如何一次性计算DataFrame多列的百分比变化(用transform函数)
使用DataFrames的transform一次性计算多列百分比变化
你的问题核心是:当用transform!处理多列时,需要明确让函数逐列执行百分比变化计算,而不是把多列作为整体处理。你之前的写法错误在于,输入的[:blue, :orange]会被打包成一个子DataFrame传给匿名函数,lag(x)会对整个子DataFrame做滞后,导致除法不是列内的自我对比。
正确实现方式
最简洁的写法是使用广播式转换(.=>),让每个输入列单独应用百分比变化函数,对应生成输出列:
using DataFrames: DataFrame using ShiftedArrays: lag prices = DataFrame( Dict( :blue => Float32[8.70,8.91,8.71,8.43,8.73], :orange => [10.66,11.08, 10.71, 11.59, 12.11] ) ) # 一次性计算两列的百分比变化 transform!(prices, [:blue, :orange] .=> (col -> col ./ lag(col) .- 1) .=> [:pct_blue, :pct_orange])
原理说明
.=>是DataFrames中的广播转换语法,会将右侧的函数分别应用到左侧的每一列上- 匿名函数
col -> col ./ lag(col) .- 1接收单个列向量,计算其百分比变化(当前值/滞后值 - 1) - 最后的
.=> [:pct_blue, :pct_orange]将每一列的计算结果映射到对应的输出列名
执行后prices会新增pct_blue和pct_orange两列,结果和你单独计算每列的方式完全一致。
另一种可选写法(自定义函数处理多列)
如果需要更复杂的多列逻辑,可以自定义函数返回包含结果的元组,再用AsTable接收:
function calculate_pct_changes(df) return ( pct_blue = df.blue ./ lag(df.blue) .- 1, pct_orange = df.orange ./ lag(df.orange) .- 1 ) end transform!(prices, [:blue, :orange] => calculate_pct_changes => AsTable)
这种方式适合需要同时处理多列关联逻辑的场景,不过对于简单的逐列相同操作,第一种广播写法更高效简洁。
内容的提问来源于stack exchange,提问作者imantha
相关产品推荐
相关产品推荐

