如何在 Julia 中对单位单位进行直方图绘制?

How to Histogram Unitful Units in Julia?

我想弄清楚如何 bin/histogram Julia 中的数据数组。我有一个来自 Unitful.jl 包的单位数组,我想使用 StatsBase 中的 Histogram 来对数据进行分类。我得到的第一个错误是一个错误,说 log10 没有使用 Unitful.FreeUnits 的方法,所以我写了一个。现在我得到一个尺寸错误。我以为 Unitful 只是要和其他东西一起工作……猜不到。以下是我所在的位置。

using Unitful
using StatsBase

data = [rand()*100*1u"MHz" for x in 1:10000]

function Base.log10(x::Quantity{})
    u = unit(x)
    return log10(x.val)u
end

# eventually I want to define my bin width manually.. but this is a start.
fit(Histogram, data)

错误

ERROR: DimensionError: 0.0 and 0.8237981449864736 MHz are not dimensionally compatible.
Stacktrace:
 [1] _lt at /home/mcamp/.julia/packages/Unitful/1t88N/src/quantities.jl:274 [inlined]
 [2] <(::Quantity{Float64,NoDims,Unitful.FreeUnits{(),NoDims,nothing}}, ::Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}}) at /home/mcamp/.julia/packages/Unitful/1t88N/src/quantities.jl:264
 [3] <(::Int64, ::Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}}) at /home/mcamp/.julia/packages/Unitful/1t88N/src/quantities.jl:266
 [4] <=(::Int64, ::Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}}) at ./operators.jl:326
 [5] >=(::Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}}, ::Int64) at ./operators.jl:350
 [6] histrange(::Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}}, ::Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}}, ::Int64, ::Symbol) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:51
 [7] histrange(::Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}, ::Int64, ::Symbol) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:39
 [8] (::StatsBase.var"#127#128"{Symbol})(::Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}, ::Int64) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:103
 [9] map(::StatsBase.var"#127#128"{Symbol}, ::Tuple{Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}}, ::Tuple{Int64}) at ./tuple.jl:176
 [10] histrange(::Tuple{Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}}, ::Tuple{Int64}, ::Symbol) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:102
 [11] fit(::Type{Histogram{Int64,N,E} where E where N}, ::Tuple{Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}}; closed::Symbol, nbins::Int64) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:332
 [12] fit(::Type{Histogram{Int64,N,E} where E where N}, ::Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}; closed::Symbol, nbins::Int64) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:276
 [13] fit(::Type{Histogram{Int64,N,E} where E where N}, ::Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:276
 [14] fit(::Type{Histogram}, ::Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}; kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:383
 [15] fit(::Type{Histogram}, ::Array{Quantity{Float64,^-1,Unitful.FreeUnits{(MHz,),^-1,nothing}},1}) at /home/mcamp/.julia/packages/StatsBase/EA8Mh/src/hist.jl:383
 [16] top-level scope at REPL[183]:1
 [17] run_repl(::REPL.AbstractREPL, ::Any) at /build/julia/src/julia-1.5.3/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288

[已编辑,因为我误解了问题]

您要绘制数据直方图吗?如果是,我将使用像 Plots.jl 这样的绘图包的 histogram 函数,而不是 StatsBase.jl。例如,要将来自 Plots.jl 的图与来自 Unitful.jl 的单位结合起来,您可以使用 UnitfulRecipes.jl 包。看看这个 MWE,它可能就是你想要的:

using Unitful: MHz
using Plots
using UnitfulRecipes
data = 100 * exp.(randn(10000)) * MHz
histogram(data)

会输出


[编辑前]

我认为对非无量纲变量(即具有单位的变量)取对数在数学上或物理上没有意义。也就是说,您重新定义 log10 恕我直言,这不是一个好主意。相反,我会在获取日志之前对数据进行非维化,类似于

using Unitful: MHz
using StatsBase
data = 100 * rand(10000) * MHz
data_nodim = log10.(data / MHz) # <- this is valid
fit(Histogram, data_nodim)      # <- this is valid too