Just write:
combine(gdf, names(gdf, r"V[0-9]{1,2}") .=> maximum)
(note the . in front of =>)
In this case the target column names will be automatically generated.
What I have written above is a shorthand for:
combine(gdf, [n => maximum for n in names(gdf, r"V[0-9]{1,2}")])
Another way to write it is:
combine(AsTable(r"V[0-9]{1,2}") => x -> map(maximum, x), gdf)
when the old column names get retained.
The combine syntax is very flexible. I recommend you to have a look at its docstring for all available options.
Consider the following examples:
julia> using DataFrames
julia> passthrough(x...) = (@show x; x)
passthrough (generic function with 1 method)
julia> df = DataFrame(Class=[1,1,2], V1=1:3, V2=11:13)
3×3 DataFrame
│ Row │ Class │ V1 │ V2 │
│ │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┤
│ 1 │ 1 │ 1 │ 11 │
│ 2 │ 1 │ 2 │ 12 │
│ 3 │ 2 │ 3 │ 13 │
julia> gdf = groupby(df, :Class)
GroupedDataFrame with 2 groups based on key: Class
First Group (2 rows): Class = 1
│ Row │ Class │ V1 │ V2 │
│ │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┤
│ 1 │ 1 │ 1 │ 11 │
│ 2 │ 1 │ 2 │ 12 │
⋮
Last Group (1 row): Class = 2
│ Row │ Class │ V1 │ V2 │
│ │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┤
│ 1 │ 2 │ 3 │ 13 │
julia> combine(gdf, r"V[0-9]{1,2}" .=> passthrough)
x = ([1, 2], [11, 12])
x = ([3], [13])
2×2 DataFrame
│ Row │ Class │ V1_V2_passthrough │
│ │ Int64 │ Tuple… │
├─────┼───────┼────────────────────┤
│ 1 │ 1 │ ([1, 2], [11, 12]) │
│ 2 │ 2 │ ([3], [13]) │
julia> combine(gdf, r"V[0-9]{1,2}" => passthrough)
x = ([1, 2], [11, 12])
x = ([3], [13])
2×2 DataFrame
│ Row │ Class │ V1_V2_passthrough │
│ │ Int64 │ Tuple… │
├─────┼───────┼────────────────────┤
│ 1 │ 1 │ ([1, 2], [11, 12]) │
│ 2 │ 2 │ ([3], [13]) │
julia> combine(gdf, names(gdf, r"V[0-9]{1,2}") .=> passthrough)
x = ([1, 2],)
x = ([3],)
x = ([11, 12],)
x = ([13],)
2×3 DataFrame
│ Row │ Class │ V1_passthrough │ V2_passthrough │
│ │ Int64 │ Tuple… │ Tuple… │
├─────┼───────┼────────────────┼────────────────┤
│ 1 │ 1 │ ([1, 2],) │ ([11, 12],) │
│ 2 │ 2 │ ([3],) │ ([13],) │
julia> combine(gdf, names(gdf, r"V[0-9]{1,2}") => passthrough)
x = ([1, 2], [11, 12])
x = ([3], [13])
2×2 DataFrame
│ Row │ Class │ V1_V2_passthrough │
│ │ Int64 │ Tuple… │
├─────┼───────┼────────────────────┤
│ 1 │ 1 │ ([1, 2], [11, 12]) │
│ 2 │ 2 │ ([3], [13]) │
In particular it is crucial to understand what gets passed to combine:
julia> r"V[0-9]{1,2}" .=> passthrough
r"V[0-9]{1,2}" => passthrough
julia> r"V[0-9]{1,2}" => passthrough
r"V[0-9]{1,2}" => passthrough
julia> names(gdf, r"V[0-9]{1,2}") .=> passthrough
2-element Array{Pair{String,typeof(passthrough)},1}:
"V1" => passthrough
"V2" => passthrough
julia> names(gdf, r"V[0-9]{1,2}") => passthrough
["V1", "V2"] => passthrough
So as you can see, all depends what gets passed to combine. In particular r"V[0-9]{1,2}" .=> passthrough and r"V[0-9]{1,2}" => passthrough are parsed as exactly the same expression, in which case passthrough is called only ONCE per group getting multiple positional arguments.
On the other hand names(gdf, r"V[0-9]{1,2}") .=> passthrough makes passthrough get called for each column separately for each group.