@@ -138,6 +138,8 @@ const TRANSFORMATION_COMMON_RULES =
138
138
transformations that return the same object without copying may create
139
139
column aliases even if `copycols=true`. An example of such a situation is
140
140
`select!(df, :a, :a => :b, :a => identity => :c)`.
141
+ As a special case in `transform` and `transform!` column renaming always
142
+ copies columns to avoid storing aliased columns in the target data frame.
141
143
142
144
If `df` is a `SubDataFrame` and `copycols=true` then a `DataFrame` is
143
145
returned and the same copying rules apply as for a `DataFrame` input: this
@@ -270,14 +272,14 @@ function normalize_selection(idx::AbstractIndex,
270
272
allunique (combine_target_col) || throw (ArgumentError (" target column names must be unique" ))
271
273
end
272
274
273
- if wanttable
274
- combine_src = AsTable (c)
275
- else
275
+ if wanttable
276
+ combine_src = AsTable (c)
277
+ else
276
278
combine_src = (length (c) == 1 ? only (c) : c)
277
279
end
278
280
279
281
combine_func = first (last (sel))
280
-
282
+
281
283
return combine_src => combine_func => combine_target_col
282
284
end
283
285
@@ -338,9 +340,9 @@ function normalize_selection(idx::AbstractIndex,
338
340
end
339
341
end
340
342
341
- if wanttable
342
- combine_src = AsTable (c)
343
- else
343
+ if wanttable
344
+ combine_src = AsTable (c)
345
+ else
344
346
combine_src = (length (c) == 1 ? only (c) : c)
345
347
end
346
348
@@ -656,8 +658,17 @@ $TRANSFORMATION_COMMON_RULES
656
658
657
659
See [`select`](@ref) for examples.
658
660
"""
659
- transform! (df:: DataFrame , @nospecialize (args... ); renamecols:: Bool = true ) =
660
- select! (df, :, args... , renamecols= renamecols)
661
+ function transform! (df:: DataFrame , @nospecialize (args... ); renamecols:: Bool = true )
662
+ idx = index (df)
663
+ newargs = Any[if sel isa Pair{<: ColumnIndex , Symbol}
664
+ idx[first (sel)] => copy => last (sel)
665
+ elseif sel isa Pair{<: ColumnIndex , <: AbstractString }
666
+ idx[first (sel)] => copy => Symbol (last (sel))
667
+ else
668
+ sel
669
+ end for sel in args]
670
+ return select! (df, :, newargs... , renamecols= renamecols)
671
+ end
661
672
662
673
function transform! (@nospecialize (arg:: Base.Callable ), df:: AbstractDataFrame ; renamecols:: Bool = true )
663
674
if arg isa Colon
@@ -978,8 +989,20 @@ ERROR: ArgumentError: column :x in returned data frame is not equal to grouping
978
989
979
990
See [`select`](@ref) for more examples.
980
991
"""
981
- transform (df:: AbstractDataFrame , @nospecialize (args... ); copycols:: Bool = true , renamecols:: Bool = true ) =
982
- select (df, :, args... , copycols= copycols, renamecols= renamecols)
992
+ function transform (df:: AbstractDataFrame , @nospecialize (args... ); copycols:: Bool = true , renamecols:: Bool = true )
993
+ idx = index (df)
994
+ # when using the copy function the copy of source data frame
995
+ # is made exactly once even if copycols=true
996
+ # (copycols=true makes a copy only if the column was not copied previously)
997
+ newargs = Any[if sel isa Pair{<: ColumnIndex , Symbol}
998
+ idx[first (sel)] => copy => last (sel)
999
+ elseif sel isa Pair{<: ColumnIndex , <: AbstractString }
1000
+ idx[first (sel)] => copy => Symbol (last (sel))
1001
+ else
1002
+ sel
1003
+ end for sel in args]
1004
+ return select (df, :, newargs... , copycols= copycols, renamecols= renamecols)
1005
+ end
983
1006
984
1007
function transform (@nospecialize (arg:: Base.Callable ), df:: AbstractDataFrame ; renamecols:: Bool = true )
985
1008
if arg isa Colon
0 commit comments