Skip to content

Commit f9ca4ad

Browse files
authored
feat: insertcols! receives kwarg after (#2829)
1 parent 0d0a463 commit f9ca4ad

File tree

3 files changed

+65
-11
lines changed

3 files changed

+65
-11
lines changed

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
* `Tables.materializer` when passed the following types or their subtypes:
2222
`AbstractDataFrame`, `DataFrameRows`, `DataFrameColumns` returns `DataFrame`.
2323
([#2839](https://github.com/JuliaData/DataFrames.jl/pull/2839))
24+
* the `insertcols!` function receives new keyword argument `after`
25+
(with `false` default) that specifies if columns should be inserted after
26+
or before `col`.
27+
([#2829](https://github.com/JuliaData/DataFrames.jl/pull/2829))
2428

2529
## Bug fixes
2630

src/dataframe/dataframe.jl

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ end
748748

749749
"""
750750
insertcols!(df::DataFrame[, col], (name=>val)::Pair...;
751-
makeunique::Bool=false, copycols::Bool=true)
751+
after::Bool=false, makeunique::Bool=false, copycols::Bool=true)
752752
753753
Insert a column into a data frame in place. Return the updated `DataFrame`.
754754
If `col` is omitted it is set to `ncol(df)+1`
@@ -763,8 +763,9 @@ If `col` is omitted it is set to `ncol(df)+1`
763763
- `val` : an `AbstractVector` giving the contents of the new column or a value of any
764764
type other than `AbstractArray` which will be repeated to fill a new vector;
765765
As a particular rule a values stored in a `Ref` or a `0`-dimensional `AbstractArray`
766-
are unwrapped and treated in the same way.
767-
- `makeunique` : Defines what to do if `name` already exists in `df`;
766+
are unwrapped and treated in the same way
767+
- `after` : if `true` columns are inserted after `col`
768+
- `makeunique` : defines what to do if `name` already exists in `df`;
768769
if it is `false` an error will be thrown; if it is `true` a new unique name will
769770
be generated by adding a suffix
770771
- `copycols` : whether vectors passed as columns should be copied
@@ -799,11 +800,33 @@ julia> insertcols!(df, 2, :c => 2:4, :c => 3:5, makeunique=true)
799800
1 │ a 2 3 1
800801
2 │ b 3 4 2
801802
3 │ c 4 5 3
803+
804+
julia> insertcols!(df, :b, :d => 7:9, after=true)
805+
3×5 DataFrame
806+
Row │ b d c c_1 a
807+
│ Char Int64 Int64 Int64 Int64
808+
─────┼──────────────────────────────────
809+
1 │ a 7 2 3 1
810+
2 │ b 8 3 4 2
811+
3 │ c 9 4 5 3
802812
```
803813
"""
804814
function insertcols!(df::DataFrame, col::ColumnIndex, name_cols::Pair{Symbol, <:Any}...;
805-
makeunique::Bool=false, copycols::Bool=true)
806-
col_ind = Int(col isa SymbolOrString ? columnindex(df, col) : col)
815+
after::Bool=false, makeunique::Bool=false, copycols::Bool=true)
816+
817+
if col isa SymbolOrString
818+
col_ind = Int(columnindex(df, col))
819+
if col_ind == 0
820+
throw(ArgumentError("column $col does not exist in data frame"))
821+
end
822+
else
823+
col_ind = Int(col)
824+
end
825+
826+
if after
827+
col_ind += 1
828+
end
829+
807830
if !(0 < col_ind <= ncol(df) + 1)
808831
throw(ArgumentError("attempt to insert a column to a data frame with " *
809832
"$(ncol(df)) columns at index $col_ind"))
@@ -894,18 +917,19 @@ function insertcols!(df::DataFrame, col::ColumnIndex, name_cols::Pair{Symbol, <:
894917
end
895918

896919
insertcols!(df::DataFrame, col::ColumnIndex, name_cols::Pair{<:AbstractString, <:Any}...;
897-
makeunique::Bool=false, copycols::Bool=true) =
920+
after::Bool=false, makeunique::Bool=false, copycols::Bool=true) =
898921
insertcols!(df, col, (Symbol(n) => v for (n, v) in name_cols)...,
899-
makeunique=makeunique, copycols=copycols)
922+
after=after, makeunique=makeunique, copycols=copycols)
900923

901924
insertcols!(df::DataFrame, name_cols::Pair{Symbol, <:Any}...;
902-
makeunique::Bool=false, copycols::Bool=true) =
903-
insertcols!(df, ncol(df)+1, name_cols..., makeunique=makeunique, copycols=copycols)
925+
after::Bool=false, makeunique::Bool=false, copycols::Bool=true) =
926+
insertcols!(df, ncol(df)+1, name_cols..., after=after,
927+
makeunique=makeunique, copycols=copycols)
904928

905929
insertcols!(df::DataFrame, name_cols::Pair{<:AbstractString, <:Any}...;
906-
makeunique::Bool=false, copycols::Bool=true) =
930+
after::Bool=false, makeunique::Bool=false, copycols::Bool=true) =
907931
insertcols!(df, (Symbol(n) => v for (n, v) in name_cols)...,
908-
makeunique=makeunique, copycols=copycols)
932+
after=after, makeunique=makeunique, copycols=copycols)
909933

910934
function insertcols!(df::DataFrame, col::Int=ncol(df)+1; makeunique::Bool=false, name_cols...)
911935
if !(0 < col <= ncol(df) + 1)

test/dataframe.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,32 @@ end
349349
@test_throws ArgumentError insertcols!(df, 2, y=2:3)
350350
end
351351

352+
@testset "insertcols! after" begin
353+
df = DataFrame(a=1:3)
354+
insertcols!(df, :a, "b" => 2:4, after=true)
355+
@test df == DataFrame(a=1:3, b=2:4)
356+
insertcols!(df, :b, "b" => 2:4, after=true, makeunique=true)
357+
@test df == DataFrame(a=1:3, b=2:4, b_1=2:4)
358+
insertcols!(df, 0, :e => 1:3, after=true)
359+
@test df == DataFrame(e=1:3, a=1:3, b=2:4, b_1=2:4)
360+
361+
@test_throws ArgumentError insertcols!(df, :a, "b" => 2:4, after=true)
362+
@test_throws DimensionMismatch insertcols!(df, :a, :c => 2:5, after=true)
363+
@test_throws ArgumentError insertcols!(df, :c, :b => 2:4, after=true, makeunique=true)
364+
@test_throws ArgumentError insertcols!(df, ncol(df)+1, :d => 1:3, after=true)
365+
@test_throws ArgumentError insertcols!(df, -1, :d => 1:3, after=true)
366+
367+
df = DataFrame(a=1:3, b=2:4)
368+
insertcols!(df, 1, :c => 7:9, after=true)
369+
@test df == DataFrame(a=1:3, c=7:9, b=2:4)
370+
371+
df = DataFrame(a=1:3)
372+
insertcols!(df, 1, :b => 2:4, :c => 7:9, after=true)
373+
@test df == DataFrame(a=1:3, b=2:4, c=7:9)
374+
insertcols!(df, "b", :b => 2:4, :c => 7:9, after=true, makeunique=true)
375+
@test df == DataFrame(a=1:3, b=2:4, b_1=2:4, c_1=7:9, c=7:9)
376+
end
377+
352378
@testset "DataFrame constructors" begin
353379
@test DataFrame([Union{Int, Missing}[1, 2, 3], Union{Float64, Missing}[2.5, 4.5, 6.5]],
354380
[:A, :B]) ==

0 commit comments

Comments
 (0)