Julia-dataframe-如何使用by()将标量强制转换为向量/多条线值

问题描述 投票:2回答:1

漫长而曲折的道路,探索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

我确信我会缺少任何帮助。

dataframe casting julia
1个回答
1
投票

当前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))

这是一个特定的解决方案,使用的事实是,在两个生成的列中,您都使用源数据帧中的同一列进行计算。

© www.soinside.com 2019 - 2024. All rights reserved.