":x / 2")) df = DataFrame(x = [1, 2, 3, 4]) df 4×1 DataFrame │ Row │ x -6ren">
gpt4 book ai didi

Julia:从表达式创建 DataFrame 列?

转载 作者:行者123 更新时间:2023-12-04 15:10:56 25 4
gpt4 key购买 nike

鉴于此:

dict = Dict(("y" => ":x / 2"))

df = DataFrame(x = [1, 2, 3, 4])

df
4×1 DataFrame
│ Row │ x │
│ │ Int64 │
├─────┼───────┤
│ 1 │ 1 │
│ 2 │ 2 │
│ 3 │ 3 │
│ 4 │ 4 │

我想做这个:

4×2 DataFrame
│ Row │ x │ y │
│ │ Int64 │ Float64 │
├─────┼───────┼─────────┤
│ 1 │ 1 │ 0.5 │
│ 2 │ 2 │ 1.0 │
│ 3 │ 3 │ 1.5 │
│ 4 │ 4 │ 2.0 │

这似乎是 DataFramesMeta 的完美应用,无论是 @with 还是 @eachrow,但我一直无法获得我的在存在 :x 的环境中按预期计算的表达式。

基本上,我希望能够遍历 dict 中的 (k, v) 对,并为每个 Symbol(k)< 创建一个新列 具有相应的值 eval(Meta.parse(v)),或类似的东西,其中发生评估的地方 Symbols:x 在评估时存在。

我没想到这会奏效,但事实并非如此:

[df[Symbol(k)] = eval(Meta.parse(v)) for (k, v) in dict]

ERROR: MethodError: no method matching /(::Symbol, ::Int64)

但这说明了问题:我需要在表达式包含的符号存在的环境中对表达式求值。

但是,将它移动到 @with 中是行不通的:

using DataFramesMeta

@with(df, [eval(Meta.parse(v)) for (k, v) in dict])

ERROR: MethodError: no method matching /(::Symbol, ::Int64)

使用 @eachrow 以同样的方式失败:

using DataFramesMeta

@eachrow df begin
for (k, v) in dict
@newcol tmp::Vector{Float32}
tmp = eval(Meta.parse(v))
end
end

ERROR: MethodError: no method matching /(::Symbol, ::Int64)

我猜我不清楚 DataFramesMeta 如何在 DataFrame 中创建环境的一些关键元素。我也不必为此使用 DataFramesMeta,任何合理简洁的选项都可以工作,因为我可以将它封装在一个包函数中。

注意:我控制了要解析成表达式的字符串的格式,但我想避免复杂性,例如在字符串中指定DataFrame对象的名称,或者广播每个操作。我希望初始字符串中的表达式语法对于非 Julia 程序员来说相当清晰。

更新:我在这个问题的评论中尝试了所有三种解决方案,但它们都有一个问题:它们在函数内部不起作用。

dict = Dict(("y" => ":x / 2"))

data = DataFrame(x = [1, 2, 3, 4])


function transform_from_dict(df, dict)

new = eval(Meta.parse("@transform(df, " * join(join.(collect(dict), " = "), ", ") * ")"))

return new

end

transform_from_dict(data, dict)

ERROR: UndefVarError: df not defined

或者:

function transform_from_dict!(df, dict)

[df[!, Symbol(k)] = eval(:(@with(df, $(Meta.parse(v))))) for (k, v) in dict]

return nothing

end

transform_from_dict!(data, dict)

ERROR: UndefVarError: df not defined

最佳答案

我和@Ajar 一起研究过这个答案,没有从那个答案中复制任何东西,我也不知道。我对 Julia 完全陌生,所以我不得不安装它(因为我认为在线编译器甚至不知道 DataFrame),后来我明白这些包必须在启动时调用,无论是在线还是离线。我添加了初学者可能需要了解的包信息。

using Pkg 
Pkg.add("DataFrames")
Pkg.add("DataFramesMeta")

using DataFrames
using DataFramesMeta
dict = Dict(("y" => ":x / 2"))
df = DataFrame(x = [1, 2, 3, 4])

@with 解决方案:

julia> function transform_from_dict!(k, v)
global df
df[!, Symbol(k)] = eval(:(@with(df, $(Meta.parse(v)))))
return nothing
end
transform_from_dict! (generic function with 2 methods)
julia> [transform_from_dict!(k, v) for (k, v) in dict]
1-element Array{Nothing,1}:
nothing
julia> df
4×2 DataFrame
Row │ x y
│ Int64 Float64
─────┼────────────────
1 │ 1 0.5
2 │ 2 1.0
3 │ 3 1.5
4 │ 4 2.0

@transform 解决方案:

julia> function transform_from_dict(df, dict)
global new
new = eval(Meta.parse("@transform(df, " * join(join.(collect(dict), " = "), ", ") * ")"))

return new

end
transform_from_dict (generic function with 1 method)
julia>

julia> transform_from_dict(data, dict)
4×2 DataFrame
Row │ x y
│ Int64 Float64
─────┼────────────────
1 │ 1 0.5
2 │ 2 1.0
3 │ 3 1.5
4 │ 4 2.0

感谢其他评论员,@Ajar 的回答中列出了基本思想。

关于Julia:从表达式创建 DataFrame 列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65208195/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com