Julia DataFrames.jl-使用NA';s(无例外)

Julia DataFrames.jl-使用NA';s(无例外),julia,Julia,我不知道如何在Julia DataFrames中处理NA 例如,使用以下数据帧: > import DataFrames > a = DataFrames.@data([1, 2, 3, 4, 5]); > b = DataFrames.@data([3, 4, 5, 6, NA]); > ndf = DataFrames.DataFrame(a=a, b=b) 我可以在列上成功执行以下操作:a > ndf[ndf[:a] .== 4, :] 但是如果我在:b上

我不知道如何在Julia DataFrames中处理
NA

例如,使用以下数据帧:

> import DataFrames
> a = DataFrames.@data([1, 2, 3, 4, 5]);
> b = DataFrames.@data([3, 4, 5, 6, NA]);
> ndf = DataFrames.DataFrame(a=a, b=b)
我可以在列
上成功执行以下操作:a

> ndf[ndf[:a] .== 4, :]
但是如果我在
:b
上尝试相同的操作,我会得到一个错误
NAException(“无法使用包含NA值的DataArray为数组编制索引”)

这是因为NA值的存在


我的问题是,通常应该如何处理带有
NA
的数据帧?我能理解你在这里想要的行为是什么?如果要进行这样的选择,可以设置条件(不是NAN)和(等于4)。如果第一次测试失败,那么第二次测试就永远不会发生

using DataFrames
a = @data([1, 2, 3, 4, 5]);
b = @data([3, 4, 5, 6, NA]);
ndf = DataFrame(a=a, b=b)
ndf[(!isna(ndf[:b]))&(ndf[:b].==4),:]
在某些情况下,您可能只想删除某些列中具有NAs的所有行

ndf = ndf[!isna(ndf[:b]),:]
关于我之前提出的问题,如果需要,可以直接在模块源代码中更改NA行为。在文件
indexing.jl
中有一个名为
Base.to_index(a::DataArray)
的函数,从第75行开始,您可以更改代码,将布尔数组中的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 
使用
isna()
忽略NA将导致源代码可读性降低,并且在大型公式中会导致性能损失:

@timeit ndf[(!isna(ndf[:b])) & (ndf[:b] .== 4),:]  #3.68 µs per loop
@timeit ndf[ndf[:b] .== 4, :]  #2.32 µs per loop

## 71x179 2D Array
@timeit dm[(!isna(dm)) & (dm .< 3)] = 1  #14.55 µs per loop  
@timeit dm[dm .< 3] = 1  #754.79 ns per loop 
@timeit ndf[(!isna(ndf[:b]))和(ndf[:b]。==4),:]#每个循环3.68µs
@timeit ndf[ndf[:b]。==4,:]#每个环路2.32µs
##71x179二维阵列
@timeit dm[(!isna(dm))和(dm.<3)]=每环路1#14.55µs
@timeit dm[dm.<3]=每环路1#754.79纳秒

在许多情况下,您希望将NA视为单独的实例,即假设NA的所有内容都是“相等”的,而其他所有内容都是不同的

如果这是您想要的行为,那么当前的DataFramesAPI对您没有多大帮助,因为
(NA==NA)
(NA==1)
都返回
NA
,而不是预期的布尔结果

这使得使用循环的数据帧过滤器非常繁琐:

函数过滤器(df,c)
对于每个箭头中的r(df)
如果(isna(c)&&isna(r:[c]))| |(!isna(r[:c])&&r[:c]==c)
...
NA
值存在或请求时,在
DataFramesMeta.jl
Query.jl
中选择类似的功能

一种解决方法是使用
isequal(a,b)
代替
a==b

test = @where(df, isequal.(:a,"cc"), isequal.(:b,NA) ) #from DataFramesMeta.jl

我认为Julia中的新语法是使用ismissing:

# drop NAs
df = DataFrame(col=[0,1,1,missing,0,1])
df = df[.!ismissing.(df[:col]),:]
# drop NAs
df = DataFrame(col=[0,1,1,missing,0,1])
df = df[.!ismissing.(df[:col]),:]