julia - Julia:从表达式创建 DataFrame 列?
问题描述
鉴于这种:
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
存在的环境中按预期进行评估。
基本上,我希望能够在(k, v)
对中进行迭代,dict
并为每个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)
但这说明了问题:我需要在它们包含的符号存在的环境中评估表达式。
但是,将其移入 a@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
解决方案
好的,结合所有评论者的答案有效!
using DataFrames
using DataFramesMeta
dict = Dict(("y" => ":x / 2"))
data = DataFrame(x = [1, 2, 3, 4])
# using @with
function transform_from_dict1(df, dict)
global df
[df[!, Symbol(k)] = eval(:(@with(df, $(Meta.parse(v))))) for (k, v) in dict]
return df
end
transform_from_dict1(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 │
而@Bogumił Kamiński的方法使用@transform
:
# using @transform
function transform_from_dict2(df, dict)
global df
new_df = eval(Meta.parse("@transform(df, " * join(join.(collect(dict), " = "), ", ") * ")"))
return new_df
end
transform_from_dict2(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 │
两者都使用来自@Lorenzglobal
的修复。
请注意,第二种形式使用的内存比第一种多 2.5 倍,可能是由于创建了第二个DataFrame
:
julia> @allocated transform_from_dict1(data, dict)
853948
julia> @allocated transform_from_dict2(data, dict)
22009111
我也认为第一种形式更清晰一些,所以这就是我在内部使用的形式。
请注意,如果您的转换中有逻辑运算符,您可能需要广播逻辑运算符,并且像往常一样,您需要预先处理任何丢失的数据问题。
推荐阅读
- flutter - 如何使用 darkTheme 在颤动中更改主题:
- r - 如何使用 ggplot2 从条形图中的多列中绘制 3 个单个数字?
- java - 如何在maven中做多个生成源代码的主类
- python - 在不更改python中的数字的情况下将变量的类型从十六进制字符串转换为uint_32
- css - 仅使用 Typescript 编译 css 文件
- nginx - 如何配置 nginx 以尾登录 Web 浏览器
- angular - 无法将 Web API 核心与 Angular 结合起来
- angular - 即使我从 Material Angular 完全复制它,dataSource 也没有显示
我知道我的问题很奇怪,但我的问题正是标题所说的。
mat-table dataSource
即使我已经尝试使用,我也没有显示任何数据console.log("My Data : ", this.dataSaource)
。不仅如此,我的控制台很干净,没有任何错误。这是我第一次使用php - Laravel 循环过滤 uuid 字符
- javascript - 如何从状态数组创建下拉列表?