如何解决在 julia 中操作数据帧时如何使用条件
当任一条件为真时,我试图找到对应于特定列的数据框元素的平均值。例如:
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_mean
但是,此代码未产生所需的输出。
请提出修复此代码段的最佳方法。 提前致谢。
解决方法
我同意 Bogumił 的评论,您应该真正查阅 Julia 文档以对该语言有基本的了解,然后浏览 DataFrames 教程。但是,我将注释您的代码以指出一些问题,以便您可以更好地进行学习:
Using Statistics
Julia(与大多数其他语言一样)区分大小写,因此编写 Using
与用于将包定义带入命名空间的保留关键字 using
不同。相关文档条目是 here
另请注意,您使用的是 DataFrames 包,因此要使您的代码可重现,您必须执行 using DataFrames,Statistics
。
df = DataFrame(value,xi,xj)
不清楚这一行应该做什么,因为传递给构造函数的参数未定义,但假设 value
、xi
和 xj
是数字向量,这不是构造 DataFrame
的正确方法:
julia> value = rand(10); xi = repeat(1:2,5); xj = rand(1:2,10);
julia> df = DataFrame(value,xj)
ERROR: MethodError: no method matching DataFrame(::Vector{Float64},::Vector{Int64},::Vector{Int64})
您可以在文档 here 中阅读有关构造函数的信息,对于像此处这样只有几列的 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
表示数组可以保存任何类型的值(浮点数、整数、字符串、概率分布...),这意味着编译器无法通过查看来预测实际内容在代码处,导致生成次优机器代码。这样做,你否定了朱莉娅的主要优势,例如基础 Python:丰富的类型系统与大量编译器优化相结合,可以在保持语言动态的同时生成高效的机器代码。在这种情况下,您知道要将 mean
函数的结果推送到结果向量中,结果向量将是一个浮点数,因此您应该使用:
julia> resulted_mean = Float64[]
Float64[]
也就是说,我根本不建议在这里进行循环(见下文)。
你的循环是:
for i in range(ncol(df))
...
这方面的一些问题:
-
Julia 中的循环需要
end
,这与 Python 中的循环结束基于代码缩进不同 -
range
是 Julia 中与 Python 中不同的函数:
julia> range(5)
ERROR: ArgumentError: At least one of `length` or `stop` must be specified
您可以使用 REPL 帮助模式了解函数(在 REPL 提示符处键入 ?
以访问它):
help?> range
search: range LinRange UnitRange StepRange StepRangeLen trailing_zeros AbstractRange trailing_ones OrdinalRange AbstractUnitRange AbstractString
range(start[,stop]; length,stop,step=1)
Given a starting value,construct a range either by length or from start to stop,optionally with a given step (defaults to 1,a UnitRange). One of length or stop is required. If length,and step are all specified,they must
agree.
...
所以你需要做类似的事情
julia> range(1,5,step = 1)
1:1:5
也就是说,对于像这样的简单范围,您可以使用冒号运算符:1:5
与 `range(1,step = 1) 相同。
- 然后您迭代从 1 到
ncol(df)
的整数 - 您可能想要检查这是否是您真正想要的,因为xi
和 { 中的值对我来说似乎不寻常{1}} 列(您在循环中过滤的列)将与 DataFrame 中的列数(即 3)相关。
在循环中,你做
xj
这又存在一些问题:首先,您将 DataFrame 的子集条件传递给 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
时,Julia 无法知道您指的是 DataFrame 列 :xi
,因此您所做的一切正在将符号 xi
与 :xi
的值进行比较,后者将始终返回 false:
i
此外,请注意 julia> :xi == 2
false
的优先级高于 |
,因此如果您想将两个相等检查组合在一起,或者您需要括号:
==
关于您的代码片段可以说更多的东西,但我希望这能让您了解您在理解上的差距以及您可以如何解决这些差距。
为了完整起见,我将如何处理您的问题 - 我将您的代码解释为“计算 julia> 1 == 1 | 2 == 2
false
julia> (1 == 1) | (2 == 2)
true
列的平均值,按 value
和 {{1} 的每个值分组},但仅限于 xi
等于 xj
":
xi
这可能是 DataFrames 最常见的分析模式,在 Bogumił 提到的教程以及 DataFrames 文档 here 中都有说明。
正如我前面所说,如果您想高效地使用 Julia,我建议您花一些时间阅读该语言本身以及您正在使用的任何关键包的文档。虽然 Julia 与 Python 有一些相似之处,并且 DataFrames 包中的某些部分具有类似于您可能在 R 中看到的东西的 API,但它本身就是一种与 Python 和 R(或任何其他语言)根本不同的语言就此而言),并且无法让自己熟悉它的实际工作原理。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。