Julia中是否存在支持缺失值的bitstype?对应场景应如何处理?
关于Julia带缺失值bitstype的问题解答
核心结论
目前Julia原生不支持将Union{Missing, T}这类多类型联合自动识别为bitstype,哪怕所有联合成员都是bitstype,也没有内置的参数化带缺失bitstype类型。
你提到的「总大小为底层最大类型大小加1比特/1字节」的逻辑是成立的,只是需要手动实现自定义类型,或者采用生态通用的替代方案。
推荐处理方案
方案1:分开存储数据与缺失掩码(通用最佳实践)
这是目前处理Mmap带缺失数组最常用的方案,不需要自定义类型,兼容性最好:
- 把数组拆成两个独立的部分分别Mmap:
- 一个是纯
T类型的数组,存储所有非缺失位置的有效值(缺失位置可以随便填占位值) - 一个是
Bool类型的掩码数组,长度和数据数组一致,对应位置标记是否为缺失
- 一个是纯
- 读写操作分别操作两个数组即可,逻辑简单清晰,也符合Julia官方DataFrames等库的缺省存储逻辑。
方案2:手动定义自定义bitstype
如果要求必须把缺失标记和数据存在同一个内存块里,可以手动实现自定义primitive type:
# 示例:实现带缺失标记的Float64 bitstype,总大小9字节(72位),1字节存标记,8字节存数据 primitive type Maybe{T} 72 end # 构造方法 function Maybe{T}(x::Union{Missing, T}) where T <: Real if ismissing(x) return reinterpret(Maybe{T}, (0x01, zero(UInt64)))[1] else return reinterpret(Maybe{T}, (0x00, reinterpret(UInt64, x)))[1] end end # 重载缺失判断方法 Base.ismissing(m::Maybe{T}) where T = reinterpret(Tuple{UInt8, UInt64}, m)[1] == 0x01 # 取值方法 function Base.getindex(m::Maybe{T}) where T @assert !ismissing(m) "Cannot get value of missing Maybe{$T}" return reinterpret(T, reinterpret(Tuple{UInt8, UInt64}, m)[2]) end
注意:实际使用时可以根据硬件对齐要求调整primitive type的总位数,比如补到128位(16字节)可以获得更好的读写性能,仅需多占用7字节空间。
内容的提问来源于stack exchange,提问作者Jeffrey
相关产品推荐
相关产品推荐

