使用包含的NA值

时间:2016-10-04 18:13:19

标签: arrays indexing julia na

我想知道为什么不能使用NA值索引Julia的DataArrays。 执行下面的剪切会导致错误(NAException(“无法使用包含NA值的DataArray索引数组”)):

dm = data([1 4 7; 2 5 8; 3 1 9])
dm[dm .== 5] = NA

dm[dm .< 3] = 1  #Error
dm[(!isna(dm)) & (dm .< 3)] = 1  #Working

有一个解决方案可以忽略带有isna()的DataFrame中的NA,就像回答here一样。乍一看它的工作方式应该如此,忽略DataFrames中的NA是与DataArrays相同的方法,因为DataFrame的每一列都是DataArray,陈述here。但在我看来,在每种情况下忽略!isna()的缺失值并不是最佳解决方案。

对于我来说,如果包含NA,DataTrame模块会抛出错误的原因尚不清楚。如果索引所需的布尔数组具有NA的值,则此值应转换为false,如MATLAB®或Pythons Pandas。在indexing.jl中的DataArray模块源代码(如下所示)中,有一个显式函数可以抛出NAException:

# Indexing with NA throws an error
function Base.to_index(A::DataArray)
    any(A.na) && throw(NAException("cannot index an array with a DataArray containing NA values"))
    Base.to_index(A.data)
end

如果您通过将NA设置为false来更改代码段

# Indexing with NA throws an error
function Base.to_index(A::DataArray)
    A[A.na] = false
    any(A.na) && throw(NAException("cannot index an array with a DataArray containing NA values"))
    Base.to_index(A.data)
end 

... dm[dm .< 3] = 1的工作方式与此类似(如在MATLAB®或Pandas中)。

对我来说,如果在索引中包含NA,则自动抛出错误是没有意义的。最低层应该是创建DataArray的参数,让用户选择是否忽略NA。有两个显着的原因:一方面,当你有具有大量索引和NA值的公式(例如计算气象网格模型)时,它不是非常适合编写和阅读代码,另一方面有明显的损失性能,这个时间测试显示:

@timeit dm[(!isna(dm)) & (dm .< 3)] = 1  #14.55 µs per loop  
@timeit dm[dm .< 3] = 1  #754.79 ns per loop

开发人员使用此异常的原因是什么,还有另一种更简单的方法,如!isna()忽略了DataArrays中的NA?

1 个答案:

答案 0 :(得分:5)

假设你有三只兔子。你想把雌兔放在与雄性不同的笼子里。你看第一只兔子,看起来像男性,所以你把它放在原处。你看第二只兔子,它看起来像一只雌性,所以你将它移到单独的笼子里。你不能真正好好看看第三只兔子。你应该怎么做?

这取决于。也许你可以把留下不知名性的兔子抛在脑后。但如果你因为不想让它们制作小兔子而将兔子分开,那么你可能希望你的分析软件告诉你它并不知道第三只兔子的性别。

这种情况经常在分析数据时出现。在大多数病理情况下,数据是系统而不是随机丢失的。如果你要调查一群人关于兔子是多么蓬松以及是否应该多吃,你可以比较mean(fluffiness[should_be_eaten_more])mean(fluffiness[!should_be_eaten_more])。但是,如果那些真的喜欢兔子的人被激怒了,你根本就在谈论吃它们,那么他们可能会把第二个问题留空。如果你忽视这一点,你会低估那些不认为兔子应该被吃掉的人的平均蓬松等级,这将是一个严重的错误。这就是fluffiness[!should_be_eaten_more]如果缺少值会抛出错误的原因:这表明无论您尝试对数据做什么都可能无法给出正确的结果。这种情况非常糟糕,以至于人们会写完整篇论文,例如: this one

足够的兔子。在索引时,有可能(并且有一天可能)更简洁的方式来删除/保留所有缺失值,但由于上述原因,它总是显式的而不是隐式的。就性能而言,虽然isna(x) & (x < 3) vs x < 3的速度有所下降,但重复索引到数组的开销也很高,而DataArrays会增加额外的开销。随着阵列变大,相对开销减少。如果这是您的代码中的瓶颈,最好的办法是以不同的方式编写代码。