@@ -107,20 +107,20 @@ as a `DataFrameRows` over a view of rows of parent of `dfr`.
107107julia> collect(Iterators.partition(eachrow(DataFrame(x=1:5)), 2))
1081083-element Vector{DataFrames.DataFrameRows{SubDataFrame{DataFrame, DataFrames.Index, UnitRange{Int64}}}}:
109109 2×1 DataFrameRows
110- Row │ x
111- │ Int64
110+ Row │ x
111+ │ Int64
112112─────┼───────
113113 1 │ 1
114114 2 │ 2
115115 2×1 DataFrameRows
116- Row │ x
117- │ Int64
116+ Row │ x
117+ │ Int64
118118─────┼───────
119119 1 │ 3
120120 2 │ 4
121121 1×1 DataFrameRows
122- Row │ x
123- │ Int64
122+ Row │ x
123+ │ Int64
124124─────┼───────
125125 1 │ 5
126126```
@@ -408,12 +408,17 @@ Base.show(dfcs::DataFrameColumns;
408408 summary= summary, eltypes= eltypes, truncate= truncate, kwargs... )
409409
410410"""
411- mapcols(f::Union{Function, Type}, df::AbstractDataFrame)
411+ mapcols(f::Union{Function, Type}, df::AbstractDataFrame; cols=All())
412+
413+ Return a `DataFrame` where each column of `df` selected by `cols` (by default, all columns)
414+ is transformed using function `f`.
415+ Columns not selected by `cols` are copied.
412416
413- Return a `DataFrame` where each column of `df` is transformed using function `f`.
414417`f` must return `AbstractVector` objects all with the same length or scalars
415418(all values other than `AbstractVector` are considered to be a scalar).
416419
420+ The `cols` column selector can be any value accepted as column selector by the `names` function.
421+
417422Note that `mapcols` guarantees not to reuse the columns from `df` in the returned
418423`DataFrame`. If `f` returns its argument then it gets copied before being stored.
419424
@@ -440,15 +445,32 @@ julia> mapcols(x -> x.^2, df)
440445 2 │ 4 144
441446 3 │ 9 169
442447 4 │ 16 196
448+
449+ julia> mapcols(x -> x.^2, df, cols=r"y")
450+ 4×2 DataFrame
451+ Row │ x y
452+ │ Int64 Int64
453+ ─────┼──────────────
454+ 1 │ 1 121
455+ 2 │ 2 144
456+ 3 │ 3 169
457+ 4 │ 4 196
443458```
444459"""
445- function mapcols (f:: Union{Function, Type} , df:: AbstractDataFrame )
460+ function mapcols (f:: Union{Function, Type} , df:: AbstractDataFrame ; cols= All ())
461+ if cols === All () || cols === Colon ()
462+ apply = Iterators. repeated (true )
463+ else
464+ picked = Set (names (df, cols))
465+ apply = Bool[name in picked for name in names (df)]
466+ end
467+
446468 # note: `f` must return a consistent length
447469 vs = AbstractVector[]
448470 seenscalar = false
449471 seenvector = false
450- for v in eachcol (df)
451- fv = f (v)
472+ for (v, doapply) in zip ( eachcol (df), apply )
473+ fv = doapply ? f (v) : copy (v)
452474 if fv isa AbstractVector
453475 if seenscalar
454476 throw (ArgumentError (" mixing scalars and vectors in mapcols not allowed" ))
@@ -470,9 +492,12 @@ function mapcols(f::Union{Function, Type}, df::AbstractDataFrame)
470492end
471493
472494"""
473- mapcols!(f::Union{Function, Type}, df::DataFrame)
495+ mapcols!(f::Union{Function, Type}, df::DataFrame; cols=All())
496+
497+ Update a `DataFrame` in-place where each column of `df` selected by `cols` (by default, all columns)
498+ is transformed using function `f`.
499+ Columns not selected by `cols` are left unchanged.
474500
475- Update a `DataFrame` in-place where each column of `df` is transformed using function `f`.
476501`f` must return `AbstractVector` objects all with the same length or scalars
477502(all values other than `AbstractVector` are considered to be a scalar).
478503
@@ -503,20 +528,39 @@ julia> df
503528 2 │ 4 144
504529 3 │ 9 169
505530 4 │ 16 196
531+
532+ julia> mapcols!(x -> 2 * x, df, cols=r"x");
533+
534+ julia> df
535+ 4×2 DataFrame
536+ Row │ x y
537+ │ Int64 Int64
538+ ─────┼──────────────
539+ 1 │ 2 121
540+ 2 │ 8 144
541+ 3 │ 18 169
542+ 4 │ 32 196
506543```
507544"""
508- function mapcols! (f:: Union{Function, Type} , df:: DataFrame )
509- # note: `f` must return a consistent length
545+ function mapcols! (f:: Union{Function,Type} , df:: DataFrame ; cols= All ())
510546 if ncol (df) == 0 # skip if no columns
511547 _drop_all_nonnote_metadata! (df)
512548 return df
513549 end
514550
551+ if cols === All () || cols === Colon ()
552+ apply = Iterators. repeated (true )
553+ else
554+ picked = Set (names (df, cols))
555+ apply = Bool[name in picked for name in names (df)]
556+ end
557+
558+ # note: `f` must return a consistent length
515559 vs = AbstractVector[]
516560 seenscalar = false
517561 seenvector = false
518- for v in eachcol (df)
519- fv = f (v)
562+ for (v, doapply) in zip ( eachcol (df), apply )
563+ fv = doapply ? f (v) : v
520564 if fv isa AbstractVector
521565 if seenscalar
522566 throw (ArgumentError (" mixing scalars and vectors in mapcols not allowed" ))
0 commit comments