Skip to content

Commit

Permalink
allow to pass a reference to where to add a column by its name (#2365)
Browse files Browse the repository at this point in the history
  • Loading branch information
bkamins authored Aug 21, 2020
1 parent 3345f69 commit c8ce235
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 12 deletions.
4 changes: 3 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
([#2308](https://github.com/JuliaData/DataFrames.jl/pull/2308))
* allow column renaming in joins
([#2313](https://github.com/JuliaData/DataFrames.jl/pull/2313)
* add `rownumber` to `DataFrameRow` ([#2356](https://github.com/JuliaData/DataFrames.jl/pull/2356))
* add `rownumber` to `DataFrameRow` ([#2356](https://github.com/JuliaData/DataFrames.jl/pull/2356))
* allow passing column name to specify the position where a new columns should be
inserted in `insertcols!` ([#2365](https://github.com/JuliaData/DataFrames.jl/pull/2365))

## Deprecated

Expand Down
25 changes: 14 additions & 11 deletions src/dataframe/dataframe.jl
Original file line number Diff line number Diff line change
Expand Up @@ -603,18 +603,20 @@ end
##############################################################################

"""
insertcols!(df::DataFrame, [ind::Int], (name=>col)::Pair...;
insertcols!(df::DataFrame, [col], (name=>val)::Pair...;
makeunique::Bool=false, copycols::Bool=true)
Insert a column into a data frame in place. Return the updated `DataFrame`.
If `ind` is omitted it is set to `ncol(df)+1`
If `col` is omitted it is set to `ncol(df)+1`
(the column is inserted as the last column).
# Arguments
- `df` : the DataFrame to which we want to add columns
- `ind` : a position at which we want to insert a column
- `col` : a position at which we want to insert a column, passed as an integer
or a column name (a string or a `Symbol`); the column selected with `col`
and columns following it are shifted to the right in `df` after the operation
- `name` : the name of the new column
- `col` : an `AbstractVector` giving the contents of the new column or a value of any
- `val` : an `AbstractVector` giving the contents of the new column or a value of any
type other than `AbstractArray` which will be repeated to fill a new vector;
As a particular rule a values stored in a `Ref` or a `0`-dimensional `AbstractArray`
are unwrapped and treated in the same way.
Expand All @@ -623,7 +625,7 @@ If `ind` is omitted it is set to `ncol(df)+1`
be generated by adding a suffix
- `copycols` : whether vectors passed as columns should be copied
If `col` is an `AbstractRange` then the result of `collect(col)` is inserted.
If `val` is an `AbstractRange` then the result of `collect(val)` is inserted.
# Examples
```jldoctest
Expand Down Expand Up @@ -655,8 +657,9 @@ julia> insertcols!(d, 2, :c => 2:4, :c => 3:5, makeunique=true)
│ 3 │ 'c' │ 4 │ 5 │ 3 │
```
"""
function insertcols!(df::DataFrame, col_ind::Int, name_cols::Pair{Symbol,<:Any}...;
function insertcols!(df::DataFrame, col::ColumnIndex, name_cols::Pair{Symbol,<:Any}...;
makeunique::Bool=false, copycols::Bool=true)
col_ind = Int(col isa SymbolOrString ? columnindex(df, col) : col)
if !(0 < col_ind <= ncol(df) + 1)
throw(ArgumentError("attempt to insert a column to a data frame with " *
"$(ncol(df)) columns at index $col_ind"))
Expand Down Expand Up @@ -744,9 +747,9 @@ function insertcols!(df::DataFrame, col_ind::Int, name_cols::Pair{Symbol,<:Any}.
return df
end

insertcols!(df::DataFrame, col_ind::Int, name_cols::Pair{<:AbstractString,<:Any}...;
insertcols!(df::DataFrame, col::ColumnIndex, name_cols::Pair{<:AbstractString,<:Any}...;
makeunique::Bool=false, copycols::Bool=true) =
insertcols!(df, col_ind, (Symbol(n) => v for (n,v) in name_cols)...,
insertcols!(df, col, (Symbol(n) => v for (n,v) in name_cols)...,
makeunique=makeunique, copycols=copycols)

insertcols!(df::DataFrame, name_cols::Pair{Symbol,<:Any}...;
Expand All @@ -758,10 +761,10 @@ insertcols!(df::DataFrame, name_cols::Pair{<:AbstractString,<:Any}...;
insertcols!(df, (Symbol(n) => v for (n,v) in name_cols)...,
makeunique=makeunique, copycols=copycols)

function insertcols!(df::DataFrame, col_ind::Int=ncol(df)+1; makeunique::Bool=false, name_cols...)
if !(0 < col_ind <= ncol(df) + 1)
function insertcols!(df::DataFrame, col::Int=ncol(df)+1; makeunique::Bool=false, name_cols...)
if !(0 < col <= ncol(df) + 1)
throw(ArgumentError("attempt to insert a column to a data frame with " *
"$(ncol(df)) columns at index $col_ind"))
"$(ncol(df)) columns at index $col"))
end
if !isempty(name_cols)
# an explicit error is thrown as keyword argument was supported in the past
Expand Down
8 changes: 8 additions & 0 deletions test/dataframe.jl
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,16 @@ end
df = DataFrame(a=Union{Int, Missing}[1, 2], b=Union{Float64, Missing}[3.0, 4.0])
@test_throws ArgumentError insertcols!(df, 5, :newcol => ["a", "b"])
@test_throws ArgumentError insertcols!(df, 0, :newcol => ["a", "b"])
@test_throws ArgumentError insertcols!(df, :z, :newcol => ["a", "b"])
@test_throws ArgumentError insertcols!(df, "z", :newcol => ["a", "b"])
@test_throws MethodError insertcols!(df, true, :newcol => ["a", "b"])
@test_throws DimensionMismatch insertcols!(df, 1, :newcol => ["a"])
@test_throws DimensionMismatch insertcols!(df, :a, :newcol => ["a"])
@test_throws DimensionMismatch insertcols!(df, "a", :newcol => ["a"])
ref1 = insertcols!(copy(df), :a, :newcol => ["a", "b"])
ref2 = insertcols!(copy(df), "a", :newcol => ["a", "b"])
@test insertcols!(df, 1, :newcol => ["a", "b"]) == df
@test ref1 == ref2 == df
@test names(df) == ["newcol", "a", "b"]
@test df.a == [1, 2]
@test df.b == [3.0, 4.0]
Expand Down

0 comments on commit c8ce235

Please sign in to comment.