Statistics 在julia中操作数据帧时如何使用条件

Statistics 在julia中操作数据帧时如何使用条件,statistics,julia,mean,Statistics,Julia,Mean,当任一条件为真时,我试图找到与特定列对应的数据帧元素的平均值。例如: Using Statistics df = DataFrame(value, xi, xj) resulted_mean = [] for i in range(ncol(df)) push!(resulted_mean, mean(df[:value], (:xi == i | :xj == i))) 这里,我正在检查xi或xj是否等于I,然后找到[:value]列中存储的所有对应值的平均值。此平均值稍后将被推送到数组

当任一条件为真时,我试图找到与特定列对应的数据帧元素的平均值。例如:


Using Statistics
df = DataFrame(value, xi, xj)
resulted_mean = []

for i in range(ncol(df))
push!(resulted_mean, mean(df[:value], (:xi == i | :xj == i)))
这里,我正在检查
xi
xj
是否等于
I
,然后找到[:value]列中存储的所有对应值的平均值。此平均值稍后将被推送到数组->
resulted\u mean

但是,此代码没有生成所需的输出

请建议修复此代码段的最佳方法。
提前感谢。

我同意Bogumił的评论,您应该真正查阅Julia文档以获得对该语言的基本理解,然后浏览DataFrames教程。不过,我将对您的代码进行注释,指出一些问题,以便您能够更好地针对您的学习:

Using Statistics
Julia(与大多数其他语言一样)区分大小写,因此使用编写
与使用
将包定义引入命名空间的保留关键字
不同。相关的文档条目是

还请注意,您使用的是DataFrames包,因此为了使代码具有可复制性,您必须使用DataFrames、Statistics执行

df = DataFrame(value, xi, xj)
由于传递给构造函数的参数未定义,因此不清楚这一行应该做什么,但是假设
value
xi
xj
是数字向量,这不是构造
数据帧的正确方法:

julia> value = rand(10); xi = repeat(1:2, 5); xj = rand(1:2, 10);

julia> df = DataFrame(value, xi, xj)
ERROR: MethodError: no method matching DataFrame(::Vector{Float64}, ::Vector{Int64}, ::Vector{Int64})
您可以在文档中阅读有关构造函数的内容,对于只有少量列的DataFrame,最常见的方法可能是:

julia> df = DataFrame(value = value, xi = xi, xj = xj)
10×3 DataFrame
 Row │ value     xi     xj    
     │ Float64   Int64  Int64 
─────┼────────────────────────
   1 │ 0.539533      1      2
   2 │ 0.652752      2      1
   3 │ 0.481461      1      2
...
那你有

resulted_mean = []
在这种情况下,我想说的是,预分配向量并在循环中推送到它的总体方法并不理想,因为它会无缘无故地增加大量的冗长内容(请参见下文),但作为一般性说明,您应该避免在Julia中使用非类型化数组:

julia> resulted_mean = []
Any[]
这里的
Any
意味着数组可以保存任何类型的值(浮点数、整数、字符串、概率分布…),这意味着编译器无法通过查看代码预测实际内容,从而生成次优的机器代码。这样做,您就否定了Julia相对于基本Python的主要优势:丰富的类型系统与大量编译器优化相结合,允许生成高效的机器代码,同时保持语言的动态性。在这种情况下,您知道要将
mean
函数的结果推送到结果向量,结果向量将是一个浮点数,因此您应该使用:

julia> resulted_mean = Float64[]
Float64[]
也就是说,我不建议在这里进行循环(见下文)

您的循环是:

for i in range(ncol(df))
    ...
这方面有几个问题:

  • Julia中的循环需要一个
    结束
    ,而Python中的循环是根据代码缩进来确定结束的

  • range
    在Julia中与Python中是不同的函数:

您可以使用REPL帮助模式了解函数(在REPL提示符处键入
以访问它):

所以你需要做一些类似的事情

julia> range(1, 5, step = 1)
1:1:5
也就是说,对于这样的简单范围,可以使用冒号运算符:
1:5
与`范围(1,5,步骤=1)相同

  • 然后对从1到
    ncol(df)
    的整数进行迭代-您可能希望检查这是否是您实际想要的,因为
    xi
    xj
    列(在循环中进行筛选)中的值与数据帧中的列数(即3)相关,这在我看来似乎很不寻常
在循环中,你是这样做的

push!(resulted_mean, mean(df[:value], (:xi == i | :xj == i)))
这同样存在一些问题:首先,您将数据帧的子集设置条件传递给
mean
函数,该函数不起作用:

julia> mean(rand(10), rand(Bool, 10))
ERROR: MethodError: objects of type Vector{Float64} are not callable
子集条件本身也有两个问题:当您编写
:xi
时,Julia无法知道您引用的是数据帧列
xi
,因此您所做的只是将符号
:xi
i
的值进行比较,这将始终返回false:

julia> :xi == 2
false
此外,请注意,
|
的优先级高于
=
,因此,如果要将两个等式检查与括号结合起来,或者需要括号:

julia> 1 == 1 | 2 == 2
false

julia> (1 == 1) | (2 == 2)
true

关于您的代码片段,可以说更多的事情,但我希望这能让您了解您在理解方面的差距在哪里,以及您可以如何消除这些差距

为了完整起见,我将如何处理您的问题-我将您的代码解释为“计算
列的平均值,按
xi
xj
的每个值分组,但仅限于
xi
等于
xj
”:

这可能是数据帧最常见的分析模式,Bogumił提到的教程以及数据帧文档中对此进行了解释


正如我前面所说的,如果您想有效地使用Julia,我建议您花一些时间阅读语言本身以及您正在使用的任何关键包的文档。虽然Julia与Python有一些相似之处,DataFrames包中的一些位有一个API,类似于您在R中看到的东西,但它本身就是一种与Python和R(或任何其他语言)根本不同的语言,没有办法让自己熟悉它的实际工作原理。

我同意Bogumił的评论,您应该真正查阅Julia文档,以获得对该语言的基本理解,然后浏览DataFrames教程。不过,我将对您的代码进行注释,指出一些问题,以便您能够更好地针对您的学习:

Using Statistics
Julia(和大多数其他语言一样)区分大小写,因此使用
编写
是不一样的
julia> 1 == 1 | 2 == 2
false

julia> (1 == 1) | (2 == 2)
true

julia> combine(groupby(df[df.xi .== df.xj, :], [:xi, :xj], sort = true), :value => mean => :resulted_mean)
2×3 DataFrame
 Row │ xi     xj     resulted_mean 
     │ Int64  Int64  Float64       
─────┼─────────────────────────────
   1 │     1      1       0.356811
   2 │     2      2       0.977041