Skip to content

Commit

Permalink
Deprecate dataframe!
Browse files Browse the repository at this point in the history
  • Loading branch information
bkamins authored Jul 29, 2020
1 parent 45284e9 commit 65ba853
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 148 deletions.
4 changes: 1 addition & 3 deletions docs/src/lib/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ selector should be passed as a `NamedTuple` to the function.
## [The design of handling of columns of a `DataFrame`](@id man-columnhandling)

When a `DataFrame` is constructed columns are copied by default. You can disable
this behavior by setting `copycols` keyword argument to `false` or by using the
[`DataFrame!`](@ref) function.
this behavior by setting `copycols` keyword argument to `false`.
The exception is if an `AbstractRange` is passed as a column, then it is always collected to a `Vector`.

Also functions that transform a `DataFrame` to produce a new `DataFrame` perform a copy of the columns,
Expand Down Expand Up @@ -114,7 +113,6 @@ AbstractDataFrame
AsTable
ByRow
DataFrame
DataFrame!
DataFrameRow
GroupedDataFrame
GroupKey
Expand Down
5 changes: 2 additions & 3 deletions docs/src/man/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -910,14 +910,13 @@ julia> x

In-place functions are safe to call, except when a view of the `DataFrame`
(created via a `view`, `@view` or [`groupby`](@ref))
or when a `DataFrame` created with `copycols=false` (or with the `DataFrame!` function)
are in use.
or when a `DataFrame` created with `copycols=false` are in use.

It is possible to have a direct access to a column `col` of a `DataFrame` `df`
using the syntaxes `df.col`, `df[!, :col]`, via the [`eachcol`](@ref) function,
by accessing a `parent` of a `view` of a column of a `DataFrame`,
or simply by storing the reference to the column vector before the `DataFrame`
was created with `copycols=false` (or with the `DataFrame!` function).
was created with `copycols=false`.

```jldoctest dataframe
julia> x = [3, 1, 2];
Expand Down
1 change: 0 additions & 1 deletion src/DataFrames.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export AbstractDataFrame,
Between,
ByRow,
DataFrame,
DataFrame!,
DataFrameRow,
GroupedDataFrame,
SubDataFrame,
Expand Down
46 changes: 0 additions & 46 deletions src/dataframe/dataframe.jl
Original file line number Diff line number Diff line change
Expand Up @@ -287,52 +287,6 @@ DataFrame(column_eltypes::AbstractVector{<:Type},
nrows::Integer=0; makeunique::Bool=false) =
DataFrame(column_eltypes, Symbol.(cnames), nrows; makeunique=makeunique)

"""
DataFrame!(args...; kwargs...)
Equivalent to `DataFrame(args...; copycols=false, kwargs...)`.
If `kwargs` contains the `copycols` keyword argument an error is thrown.
# Examples
```jldoctest
julia> df1 = DataFrame(a=1:3)
3×1 DataFrame
│ Row │ a │
│ │ Int64 │
├─────┼───────┤
│ 1 │ 1 │
│ 2 │ 2 │
│ 3 │ 3 │
julia> df2 = DataFrame!(df1)
julia> df1.a === df2.a
true
```
"""
function DataFrame!(args...; kwargs...)
if :copycols in keys(kwargs)
throw(ArgumentError("`copycols` keyword argument is not allowed"))
end
DataFrame(args...; copycols=false, kwargs...)
end

DataFrame!(columns::AbstractMatrix,
cnames::Union{AbstractVector{Symbol},
AbstractVector{<:AbstractString}} = gennames(size(columns, 2));
makeunique::Bool=false) =
throw(ArgumentError("It is not possible to construct a `DataFrame` from " *
"`$(typeof(columns))` without allocating new columns: " *
"use `DataFrame(...)` instead"))


DataFrame!(column_eltypes::AbstractVector{<:Type},
cnames::Union{AbstractVector{Symbol}, AbstractVector{<:AbstractString}},
nrows::Integer=0; makeunique::Bool=false)::DataFrame =
throw(ArgumentError("It is not possible to construct an uninitialized `DataFrame`" *
"without allocating new columns: use `DataFrame(...)` instead"))

##############################################################################
##
## AbstractDataFrame interface
Expand Down
2 changes: 2 additions & 0 deletions src/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,5 @@ import Base: map
@deprecate map(f::Base.Callable, gd::GroupedDataFrame) combine(f, gd, ungroup=false)
@deprecate map(f::Pair{<:ColumnIndex}, gd::GroupedDataFrame) combine(f, gd, ungroup=false)
@deprecate map(f::Pair, gd::GroupedDataFrame) combine(AsTable(first(f)) => last(f), gd, ungroup=false)

@deprecate DataFrame!(args...; kwargs...) DataFrame(args...; copycols=false, kwargs...)
2 changes: 1 addition & 1 deletion src/groupeddataframe/splitapplycombine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ function _combine(f::AbstractVector{<:Pair},
# this check is redundant given we check idx above
# but it is safer to double check and it is cheap
@assert all(x -> length(x) == length(outcols[1]), outcols)
return idx, DataFrame!(collect(AbstractVector, outcols), nms)
return idx, DataFrame(collect(AbstractVector, outcols), nms, copycols=false)
end

function _combine(fun::Base.Callable, gd::GroupedDataFrame, ::Nothing,
Expand Down
4 changes: 0 additions & 4 deletions src/other/tables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ end
# This supports the Tables.RowTable type; needed to avoid ambiguities w/ another constructor
DataFrame(x::AbstractVector{NamedTuple{names, T}}; copycols::Bool=true) where {names, T} =
fromcolumns(Tables.columns(Tables.IteratorWrapper(x)), collect(names), copycols=false)
DataFrame!(x::AbstractVector{<:NamedTuple}) =
throw(ArgumentError("It is not possible to construct a `DataFrame` from " *
"`$(typeof(x))` without allocating new columns: use " *
"`DataFrame(x)` instead"))

Tables.istable(::Type{<:Union{DataFrameRows,DataFrameColumns}}) = true
Tables.columnaccess(::Type{<:Union{DataFrameRows,DataFrameColumns}}) = true
Expand Down
114 changes: 40 additions & 74 deletions test/constructors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const ≅ = isequal
@test isempty(_columns(df))
@test _columns(df) isa Vector{AbstractVector}
@test index(df) == Index()
@test size(DataFrame!()) == (0,0)
@test size(DataFrame(copycols=false)) == (0,0)

vecvec = [CategoricalVector{Union{Float64, Missing}}(zeros(3)),
CategoricalVector{Union{Float64, Missing}}(ones(3))]
Expand All @@ -23,25 +23,25 @@ const ≅ = isequal
@test size(df, 1) == 3
@test size(df, 2) == 2

df2 = DataFrame!(collect(Any, vecvec), Index([:x1, :x2]))
df2 = DataFrame(collect(Any, vecvec), Index([:x1, :x2]), copycols=false)
@test size(df2, 1) == 3
@test size(df2, 2) == 2
@test df2.x1 === vecvec[1]
@test df2.x2 === vecvec[2]

for fun in (DataFrame, DataFrame!)
@test df == fun(vecvec)
@test df == fun(collect(Any, vecvec))
@test df == fun(collect(AbstractVector, vecvec))
@test df == fun(Tuple(vecvec))
@test df == fun(x1 = vecvec[1], x2 = vecvec[2])
for copycolsarg in (true, false)
@test df == DataFrame(vecvec, copycols=copycolsarg)
@test df == DataFrame(collect(Any, vecvec), copycols=copycolsarg)
@test df == DataFrame(collect(AbstractVector, vecvec), copycols=copycolsarg)
@test df == DataFrame(Tuple(vecvec), copycols=copycolsarg)
@test df == DataFrame(x1 = vecvec[1], x2 = vecvec[2], copycols=copycolsarg)

for cols in ([:x1, :x2], ["x1", "x2"])
@test df == fun(vecvec, cols)
@test df == fun(collect(Any, vecvec), cols)
@test df == fun(collect(AbstractVector, vecvec), cols)
@test df == fun(Tuple(vecvec), Tuple(cols))
@test df == fun([col=>vect for (col, vect) in zip(cols, vecvec)])
@test df == DataFrame(vecvec, cols, copycols=copycolsarg)
@test df == DataFrame(collect(Any, vecvec), cols, copycols=copycolsarg)
@test df == DataFrame(collect(AbstractVector, vecvec), cols, copycols=copycolsarg)
@test df == DataFrame(Tuple(vecvec), Tuple(cols), copycols=copycolsarg)
@test df == DataFrame([col=>vect for (col, vect) in zip(cols, vecvec)], copycols=copycolsarg)
end
end

Expand Down Expand Up @@ -97,9 +97,9 @@ const ≅ = isequal
@test df[!, "x1"] == df2[!, "x1"]
@test df[!, "x2"] == df2[!, "x2"]

@test_throws ArgumentError DataFrame!([0.0 1.0;
0.0 1.0;
0.0 1.0])
@test_throws MethodError DataFrame([0.0 1.0;
0.0 1.0;
0.0 1.0], copycols=false)

df2 = DataFrame([0.0 1.0;
0.0 1.0;
Expand All @@ -115,9 +115,9 @@ const ≅ = isequal
@test df[!, :x1] == df2[!, :a]
@test df[!, :x2] == df2[!, :b]

@test_throws ArgumentError DataFrame!([0.0 1.0;
0.0 1.0;
0.0 1.0], [:a, :b])
@test_throws MethodError DataFrame([0.0 1.0;
0.0 1.0;
0.0 1.0], [:a, :b], copycols=false)

df2 = DataFrame([0.0 1.0;
0.0 1.0;
Expand All @@ -126,9 +126,9 @@ const ≅ = isequal
@test df[!, "x1"] == df2[!, "a"]
@test df[!, "x2"] == df2[!, "b"]

@test_throws ArgumentError DataFrame!([0.0 1.0;
0.0 1.0;
0.0 1.0], ["a", "b"])
@test_throws MethodError DataFrame([0.0 1.0;
0.0 1.0;
0.0 1.0], ["a", "b"], copycols=false)

@test df == DataFrame(x1 = Union{Float64, Missing}[0.0, 0.0, 0.0],
x2 = Union{Float64, Missing}[1.0, 1.0, 1.0])
Expand Down Expand Up @@ -176,12 +176,11 @@ end
@test df.y === y
@test_throws ArgumentError DataFrame(x=x, y=y, copycols=1)

df = DataFrame!(x=x, y=y)
df = DataFrame(x=x, y=y, copycols=false)
@test size(df) == (3, 2)
@test propertynames(df) == [:x, :y]
@test df.x === x
@test df.y === y
@test_throws ArgumentError DataFrame!(x=x, y=y, copycols=true)
end

@testset "DataFrame constructor" begin
Expand Down Expand Up @@ -216,11 +215,6 @@ end
@test df1 == df2
@test df1.x === df2.x
@test df1.y === df2.y

df2 = DataFrame!(df1)
@test df1 == df2
@test df1.x === df2.x
@test df1.y === df2.y
end

@testset "pair constructor" begin
Expand All @@ -238,11 +232,8 @@ end
@test propertynames(df) == [:a, :b, :c]
@test df.a == a
@test df.a !== a
df = DataFrame(:a=>a, :b=>1, :c=>1:3, copycols=false)
@test propertynames(df) == [:a, :b, :c]
@test df.a === a

df = DataFrame!(:a=>a, :b=>1, :c=>1:3)
df = DataFrame(:a=>a, :b=>1, :c=>1:3, copycols=false)
@test propertynames(df) == [:a, :b, :c]
@test df.a === a

Expand All @@ -260,11 +251,8 @@ end
@test propertynames(df) == [:a, :b, :c]
@test df."a" == a
@test df."a" !== a
df = DataFrame("a"=>a, "b"=>1, "c"=>1:3, copycols=false)
@test propertynames(df) == [:a, :b, :c]
@test df."a" === a

df = DataFrame!("a"=>a, "b"=>1, "c"=>1:3)
df = DataFrame("a"=>a, "b"=>1, "c"=>1:3, copycols=false)
@test propertynames(df) == [:a, :b, :c]
@test df."a" === a
end
Expand All @@ -280,11 +268,8 @@ end
@test propertynames(df) == [:a, :b, :c]
@test df.a == a
@test df.a !== a
df = DataFrame(Dict(:a=>a, :b=>1, :c=>1:3), copycols=false)
@test propertynames(df) == [:a, :b, :c]
@test df.a === a

df = DataFrame!(Dict(:a=>a, :b=>1, :c=>1:3))
df = DataFrame(Dict(:a=>a, :b=>1, :c=>1:3), copycols=false)
@test propertynames(df) == [:a, :b, :c]
@test df.a === a

Expand All @@ -301,10 +286,6 @@ end
df = DataFrame(Dict("a"=>a, "b"=>1, "c"=>1:3), copycols=false)
@test propertynames(df) == [:a, :b, :c]
@test df."a" === a

df = DataFrame!(Dict("a"=>a, "b"=>1, "c"=>1:3))
@test propertynames(df) == [:a, :b, :c]
@test df."a" === a
end

@testset "vector constructors" begin
Expand Down Expand Up @@ -379,11 +360,6 @@ end
@test df.x1 === x
@test df.x2 === y

df = DataFrame!((x, y))
@test propertynames(df) == [:x1, :x2]
@test df.x1 === x
@test df.x2 === y

df = DataFrame((x, y), (:x1, :x2))
@test propertynames(df) == [:x1, :x2]
@test df.x1 == x
Expand Down Expand Up @@ -418,21 +394,11 @@ end
@test df."x1" === x
@test df."x2" === y

df = DataFrame!((x, y), (:x1, :x2))
@test propertynames(df) == [:x1, :x2]
@test df.x1 === x
@test df.x2 === y

n = [:x1, :x2]
v = AbstractVector[1:3, [1,2,3]]
@test DataFrame(v, n).x1 isa Vector{Int}
@test v[1] isa AbstractRange

df = DataFrame!((x, y), ("x1", "x2"))
@test names(df) == ["x1", "x2"]
@test df."x1" === x
@test df."x2" === y

n = ["x1", "x2"]
v = AbstractVector[1:3, [1,2,3]]
@test DataFrame(v, n)."x1" isa Vector{Int}
Expand All @@ -443,22 +409,22 @@ end
@test DataFrame(a = 1:5, b = 1) == DataFrame(a = collect(1:5), b = fill(1, 5))
@test DataFrame(a = 1, b = 1:5) == DataFrame(a = fill(1, 5), b = collect(1:5))
@test size(DataFrame(a=1, b=[])) == (0, 2)
@test size(DataFrame!(a=1, b=[])) == (0, 2)
@test size(DataFrame(a=1, b=[], copycols=false)) == (0, 2)
end

@testset "constructor thrown exceptions" begin
for f in [DataFrame, DataFrame!]
@test_throws DimensionMismatch f(Any[collect(1:10)], DataFrames.Index([:A, :B]))
@test_throws ArgumentError f(A = rand(2,2))
@test_throws ArgumentError f(A = rand(2,1))
@test_throws ArgumentError f([1, 2, 3])
@test_throws DimensionMismatch f(AbstractVector[1:3, [1,2]])
@test_throws ArgumentError f([1:3, 1], [:x1, :x2])
@test_throws ArgumentError f([1:3, 1], ["x1", "x2"])
@test_throws ErrorException f([1:3, 1])
for copycolsarg in (true, false)
@test_throws DimensionMismatch DataFrame(Any[collect(1:10)], DataFrames.Index([:A, :B]), copycols=copycolsarg)
@test_throws ArgumentError DataFrame(A = rand(2,2), copycols=copycolsarg)
@test_throws ArgumentError DataFrame(A = rand(2,1), copycols=copycolsarg)
@test_throws ArgumentError DataFrame([1, 2, 3], copycols=copycolsarg)
@test_throws DimensionMismatch DataFrame(AbstractVector[1:3, [1,2]], copycols=copycolsarg)
@test_throws ArgumentError DataFrame([1:3, 1], [:x1, :x2], copycols=copycolsarg)
@test_throws ArgumentError DataFrame([1:3, 1], ["x1", "x2"], copycols=copycolsarg)
@test_throws ErrorException DataFrame([1:3, 1], copycols=copycolsarg)
end

@test_throws MethodError DataFrame!([1 2; 3 4], copycols=false)
@test_throws MethodError DataFrame([1 2; 3 4], copycols=false)
end

@testset "column types" begin
Expand All @@ -478,7 +444,7 @@ end
@test size(df) == (2, 2)
@test df.x1 == [1, 3]
@test df.x2 == [2, 4]
@test_throws ArgumentError DataFrame!([1 2; 3 4])
@test_throws MethodError DataFrame([1 2; 3 4], copycols=false)

end

Expand Down Expand Up @@ -509,8 +475,8 @@ end
@test size(df) == (2, 2)
@test eltype.(eachcol(df)) == [Union{Int, Missing}, Union{Float64, Missing}]

@test_throws ArgumentError DataFrame!([Union{Int, Missing}, Union{Float64, Missing}],
[:x1, :x2], 2)
@test_throws MethodError DataFrame([Union{Int, Missing}, Union{Float64, Missing}],
[:x1, :x2], 2, copycols=false)
@test size(df) == (2, 2)
@test eltype.(eachcol(df)) == [Union{Int, Missing}, Union{Float64, Missing}]

Expand Down
Loading

0 comments on commit 65ba853

Please sign in to comment.