2015-07-09 19 views
6

Tôi không chắc chắn cách xử lý NA trong Julia DataFrames.Julia DataFrames.jl - lọc dữ liệu với NA (NAException)

Ví dụ với DataFrame sau:

> import DataFrames 
> a = [email protected]([1, 2, 3, 4, 5]); 
> b = [email protected]([3, 4, 5, 6, NA]); 
> ndf = DataFrames.DataFrame(a=a, b=b) 

tôi có thể thực hiện thành công các hoạt động sau đây trên cột :a

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

nhưng nếu tôi cố gắng hoạt động tương tự trên :b tôi nhận được một lỗi 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 

Điều này là do sự có mặt của giá trị NA.

Câu hỏi của tôi là DataFrames với NA thường nên được xử lý như thế nào? Tôi có thể hiểu rằng hoạt động > hoặc < chống lại NA sẽ là undefined nhưng == sẽ hoạt động (không?).

Trả lời

5

Hành vi mong muốn của bạn ở đây là gì? Nếu bạn muốn thực hiện các lựa chọn như thế này, bạn có thể tạo điều kiện (không phải là NAN) AND (bằng 4). Nếu thử nghiệm đầu tiên thất bại thì thử nghiệm thứ hai sẽ không bao giờ xảy ra.

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),:] 

Trong một số trường hợp, bạn chỉ có thể muốn thả tất cả các hàng bằng NA ở một số cột

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

Về this câu hỏi tôi hỏi trước đây, bạn có thể thay đổi hành vi NA này trực tiếp trong các module mã nguồn nếu bạn muốn. Trong tệp indexing.jl có hàm có tên Base.to_index(A::DataArray) bắt đầu ở dòng 75, nơi bạn có thể thay đổi mã để đặt NA trong mảng boolean thành false. Ví dụ, bạn có thể làm như sau:

# 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 

Bỏ qua NA với isna() sẽ gây ra một sourcecode ít có thể đọc được và trong công thức lớn, một sự mất mát hiệu suất:

@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 
0

Trong nhiều trường hợp bạn muốn để điều trị NA như trường hợp riêng biệt, tức là giả định rằng mọi thứ là NA là "bình đẳng" và mọi thứ khác là khác nhau.

Nếu đây là hành vi bạn muốn, API DataFrames hiện tại không giúp bạn nhiều, vì cả hai (NA == NA)(NA == 1) trả lại NA thay vì kết quả boolean dự kiến ​​của chúng.

Điều này làm cho bộ lọc DataFrame vô cùng tẻ nhạt bằng vòng: function filter(df,c) for r in eachrow(df) if (isna(c) && isna(r:[c])) || (!isna(r[:c]) && r[:c] == c ) ... và phá vỡ chức năng chọn giống như trong DataFramesMeta.jlQuery.jl khi NA giá trị hiện tại hay yêu cầu ..

Một workaround là sử dụng isequal(a,b) ở vị trí của a==b

test = @where(df, isequal.(:a,"cc"), isequal.(:b,NA)) #from DataFramesMeta.jl 
Các vấn đề liên quan