我不确定如何在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
应该有效(不是?)。
答案 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.jl
和NA
会打破类似于选择的功能。
一种解决方法是使用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]),:]