如何根据Julia中列中的值查找数据框行的平均值?

Qwe*_*rty 3 julia

我在 Julia 中有以下数据框。

using DataFrames 
data = DataFrame(Value = [23, 56, 10, 48, 51], Type = ["A", "B", "A", "B", "B"])

5×2 DataFrame
? Row ? Value ? Type   ?
?     ? Int64 ? String ?
????????????????????????
? 1   ? 23    ? A      ?
? 2   ? 56    ? B      ?
? 3   ? 10    ? A      ?
? 4   ? 48    ? B      ?
? 5   ? 51    ? B      ?
Run Code Online (Sandbox Code Playgroud)

如何根据列Type获得列Value的平均值?

Bog*_*ski 5

如果您想要性能,请考虑以下选项

julia> using DataFrames

julia> using Statistics

julia> using BenchmarkTools

julia> data = DataFrame(Value = rand(1:10, 10^6),
                        Type = categorical(rand(["A", "B"], 10^6)));
Run Code Online (Sandbox Code Playgroud)

请注意,我将:Type列生成为分类列,因为稍后聚合会快得多。

首先是上面答案的时间:

julia> @benchmark by($data, [:Type], df -> mean(df[:, :Value]))
BenchmarkTools.Trial: 
  memory estimate:  30.53 MiB
  allocs estimate:  212
  --------------
  minimum time:     12.173 ms (0.00% GC)
  median time:      13.305 ms (3.63% GC)
  mean time:        14.229 ms (4.30% GC)
  maximum time:     20.491 ms (2.98% GC)
  --------------
  samples:          352
  evals/sample:     1
Run Code Online (Sandbox Code Playgroud)

这是我更改df[:, :Value]df.Value. 不同之处在于df.Value不会不必要地复制数据。您可以看到,您已经节省了 10% 以上的运行时间:

julia> @benchmark by($data, :Type, df -> mean(df.Value))
BenchmarkTools.Trial: 
  memory estimate:  22.90 MiB
  allocs estimate:  203
  --------------
  minimum time:     10.926 ms (0.00% GC)
  median time:      13.151 ms (1.92% GC)
  mean time:        13.093 ms (3.53% GC)
  maximum time:     16.933 ms (3.25% GC)
  --------------
  samples:          382
  evals/sample:     1
Run Code Online (Sandbox Code Playgroud)

这是一种有效的编写方法。此语句意味着我们将列传递给:Value函数mean

julia> @benchmark by($data, :Type, :Value => mean)
BenchmarkTools.Trial: 
  memory estimate:  15.27 MiB
  allocs estimate:  190
  --------------
  minimum time:     8.326 ms (0.00% GC)
  median time:      8.667 ms (0.00% GC)
  mean time:        9.599 ms (2.74% GC)
  maximum time:     17.364 ms (3.57% GC)
  --------------
  samples:          521
  evals/sample:     1
Run Code Online (Sandbox Code Playgroud)

最后,让我们检查差异 if :Valueis a Vector{String}(在另一个答案中给出的方法):

julia> data.Type = String.(data.Type);

julia> @benchmark by($data, [:Type], df -> mean(df[:, :Value]))
BenchmarkTools.Trial: 
  memory estimate:  46.16 MiB
  allocs estimate:  197
  --------------
  minimum time:     26.664 ms (2.08% GC)
  median time:      27.197 ms (2.11% GC)
  mean time:        27.486 ms (2.11% GC)
  maximum time:     35.740 ms (1.64% GC)
  --------------
  samples:          182
  evals/sample:     1
Run Code Online (Sandbox Code Playgroud)

你可以看到它比推荐的答案慢了大约三倍。另请注意:

julia> by(data, :Type, :Value => mean)
2×2 DataFrame
? Row ? Type   ? Value_mean ?
?     ? String ? Float64    ?
?????????????????????????????
? 1   ? B      ? 5.50175    ?
? 2   ? A      ? 5.49524    ?
Run Code Online (Sandbox Code Playgroud)

为生成的列生成更好的默认名称(因为它知道源列名称和转换函数名称)。