JuliaStats/DataFrames.jl — pull request #566 by timema (2014-03-15 16:37:34+00:00)
Title: convert(DataFrame,Matrix) won't work with NA's or ModelMatrix

When converting a matrix to a DataFrame using DataFrame(Matrix) it warns that you need to use convert instead of the DataFrame function. Currently convert() will make a dataframe but the columns are not DataArrays; therefore, it does not work in the ModelMatrix function (i think it fails in the internal cols() function and NA's cannot be assigned to it. Also, with the convert() function, you cannot assign names in the original construction of the dataframe. Below is some basic code illustrating it and at the bottom is a possible change to base.convert that would fix it. Of course, I am may completely misunderstand what direction was being taken with this.

julia> using DataFrames
julia> using GLM
julia> df=DataFrame(randn(50,3));
WARNING: DataFrame(::Matrix, ::Vector)) is deprecated, use convert(DataFrame, Matrix) instead
in DataFrame at /Users/madmax/.julia/v0.3/DataFrames/src/deprecated.jl:53 (repeats 2 times)

#can make DataFrame with convert()
julia> df2=convert(DataFrame,randn(50,3));

#first data frame works
ulia> m1=lm(x1~x2+x3,df)
Formula: x1 ~ x2 + x3

Coefficients:
Estimate Std.Error t value Pr(>|t|)
(Intercept) -0.161801 0.147976 -1.09343 0.2798
x2 0.174929 0.137049 1.2764 0.2081
x3 -0.143516 0.146441 -0.980023 0.3321

#second data frame does not
julia> m2=lm(x1~x2+x3,df2)
ERROR: no method cols(Array{Float64,1})
in ModelMatrix at /Users/madmax/.julia/v0.3/DataFrames/src/formula/formula.jl:232
in lm at /Users/madmax/.julia/v0.3/GLM/src/lm.jl:39

#first data frame works
julia> df[1,1]=NA
NA

#second data frame does not
julia> df2[1,1]=NA

ERROR: no method convert(Type{Float64}, NAtype)
in setindex! at array.jl:349
in insert_single_entry! at /Users/madmax/.julia/v0.3/DataFrames/src/dataframe/dataframe.jl:421
in setindex! at /Users/madmax/.julia/v0.3/DataFrames/src/dataframe/dataframe.jl:504

julia> typeof(df[1])
DataArray{Float64,1} (constructor with 1 method)

julia> typeof(df2[1])
Array{Float64,1}

#Original Base.convert:
function Base.convert(::Type{DataFrame}, A::Matrix)
n = size(A, 2)
cols = Array(Any, n)
for i in 1:n
cols[i] = A[:, i]
end
return DataFrame(cols, Index(gennames(n)))
end

#new Base.convert that make cols DataArray's and allows options to include names
function Base.convert(::Type{DataFrame}, A::Matrix, cn::Vector = gennames(size(A, 2)))
n = size(A, 2)
cols = Array(Any, n)
for i in 1:n
cols[i] = DataArray(A[:, i])
end
return DataFrame(cols, Index(cn))
end