漫长而曲折的道路,探索DataFrames.jl和另一个问题。
我正试图强制转换返回标量的函数以映射回整个向量。我不确定这是否很清楚,所以让我举例说明:
假设我正在运行以下(现在是规范的)示例
df = DataFrame(grp = rand(["a","b"], 100), x= rand(100), y = rand(100), z=rand(100));
by(df, :grp,result= (:x) => (x) -> sum(x))
2×2 DataFrame
│ Row │ grp │ result │
│ │ String │ Float64 │
├─────┼────────┼─────────┤
│ 1 │ b │ 30.431 │
│ 2 │ a │ 19.9667 │
对于每个组,我得到x的总和。都好。但是出于某种原因,我想为数据集中的每一行强制使用每个组的总和]
我发现了以下hack
by(df, :grp,result= (:x) => (x) -> x.-x.+sum(x))
完全符合我的期望
│ Row │ grp │ result │
│ │ String │ Float64 │
├─────┼────────┼─────────┤
│ 1 │ b │ 30.431 │
│ 2 │ b │ 30.431 │
│ 3 │ b │ 30.431 │
⋮
│ 98 │ a │ 19.9667 │
│ 99 │ a │ 19.9667 │
│ 100 │ a │ 19.9667 │
现在,我实质上是在函数中强制矢量方面使其实现((我也以最不雅观的方式进行)。
我的问题是:by()是否有一种正确/更正确的方法来强制函数返回标量以映射回原始矢量?
我认为这将非常有帮助,也有助于解决以下情况。
by(df, :grp,result= (:x) => (x) -> sum(x),result2= (:x) => (x) -> mean(x)) # works returns 2 lines
by(df, :grp,result= (:x) => (x) -> sum(x),result2= (:x) => (x) -> x.-5) # doesnt work (scalar vs vector)
by(df, :grp,result= (:x) => (x) -> x.-x.+sum(x),result2= (:x) => (x) -> x.-5) # works returns 100 lines
我确信我会缺少任何帮助。
当前by
并未限制转换函数应返回的行数。唯一的限制是,如果传递了多个函数,则它们必须返回相同数量的行。
这是您可以选择执行的操作:
by(df, :grp,result= :x => x -> fill(sum(x), length(x)))
您可以使用的一种通用方法,速度稍慢,但更灵活的是通过以下方式使用by
(我正在重写您的示例by(df, :grp,result= (:x) => (x) -> sum(x),result2= (:x) => (x) -> x.-5)
,该方法无效):
by(df, :grp) do sdf
DataFrame(result = sum(sdf.x), result2 = sdf.x .- 5)
end
这里您将整个SubDataFrame
传递给分组函数,并使用DataFrame
构造函数的隐式广播功能。
您的特定示例也可以写成:
by(df, :grp, :x => x -> DataFrame(result = sum(x), result2 = x .- 5))
这是一个特定的解决方案,使用的事实是,在两个生成的列中,您都使用源数据帧中的同一列进行计算。