Julia DataFrames.jl - 使用NA&#39过滤数据(NAException)

时间:2015-07-09 23:07:25

标签: julia

我不确定如何在Julia DataFrames中处理NA

例如,使用以下DataFrame:

> 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("cannot index an array with a DataArray containing NA values")

> ndf[ndf[:b] .== 4, :]

NAException("cannot index an array with a DataArray containing NA values")
while loading In[108], in expression starting on line 1

in to_index at /Users/abisen/.julia/v0.3/DataArrays/src/indexing.jl:85
in getindex at /Users/abisen/.julia/v0.3/DataArrays/src/indexing.jl:210
in getindex at /Users/abisen/.julia/v0.3/DataFrames/src/dataframe/dataframe.jl:268

这是因为存在NA值。

我的问题是,应该如何处理带有NA的DataFrame?我可以理解,针对>的{​​{1}}或<操作将为NA,但undefined应该有效(不是?)。

4 个答案:

答案 0 :(得分:5)

这里你想要的行为是什么?如果你想做这样的选择你可以使条件(不是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),:]

在某些情况下,您可能只想删除某些列中具有NA的所有行

ndf = ndf[!isna(ndf[:b]),:]

答案 1 :(得分:1)

关于我之前询问过的this问题,如果需要,可以直接在模块源代码中更改此NA行为。在文件indexing.jl中,从第75行开始有一个名为Base.to_index(A::DataArray)的函数,您可以在其中更改代码以将布尔数组中的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 

答案 2 :(得分:0)

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

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

这使得使用循环的非常繁琐的DataFrame过滤器: function filter(df,c) for r in eachrow(df) if (isna(c) && isna(r:[c])) || ( !isna(r[:c]) && r[:c] == c ) ... DataFramesMeta.jl值存在或请求时,Query.jlNA会打破类似于选择的功能。

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

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

答案 3 :(得分:0)

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

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