StatsPlots中构造Symbol的代码为何失效?求简便修复方案
问题解析与修复
问题背景
以下代码能正常生成密度图:
using DataFrames, StatsPlots df = DataFrame(A = rand(20), C = repeat([1,2,3, 4], inner = 5)) plt_dens1 = @df df density( :A, group = :C, title = "This works" )
但如果用变量传递列名Symbol,代码会报错:
asymb = Symbol("A") csymb = Symbol("C") plt_dens2 = @df df density( asymb, group = csymb, title = "This doesn't work" )
错误信息开头是:
ERROR: MethodError: no method matching _extract_group_attributes(::Symbol, ::Symbol)
虽然直接索引DataFrame列能解决,但写法太繁琐:
plt_dens3 = @df df density( df[:, Symbol("A")], group = df[:, Symbol("C")], title = "This also works" )
为啥plt_dens2跑不起来?
@df宏是在宏展开阶段(代码实际运行前的编译预处理阶段)工作的,它只会识别直接写在代码里的Symbol字面量(比如:A),自动把它替换成df[:, :A]来引用列数据。但asymb是你在运行时定义的变量,宏展开的时候根本不知道这个变量里存的是列名Symbol,只会把asymb本身作为参数传给density函数。这时候group = csymb相当于把两个Symbol直接扔给了分组逻辑,而函数需要的是分组数据而非Symbol,自然就触发方法匹配错误了。
简单修复办法
在@df宏里用插值符号$,把变量里的Symbol值注入到宏展开的代码中,让宏把它当成:A这种字面量处理:
asymb = Symbol("A") csymb = Symbol("C") plt_dens2 = @df df density( $asymb, group = $csymb, title = "This works now!" )
宏展开时,$asymb会被替换成:A(也就是变量存储的Symbol值),后续逻辑就和直接写:A完全一样,能正常生成图表。
内容的提问来源于stack exchange,提问作者Soldalma
相关产品推荐
相关产品推荐

