# Combine(groupby())

**URL:** <https://discourse.julialang.org/t/combine-groupby/139142>\
**Category:** New to Julia\
**Tags:** dataframes\
**Created:** [September 1, 2026, 3:49pm UTC](https://discourse.julialang.org/t/combine-groupby/139142 "2026-09-01T15:49:15Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![mahmah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mahmah/32/214326_2.png) [@mahmah](https://discourse.julialang.org/u/mahmah)\
**Post date:** [September 1, 2026, 3:49pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/1 "2026-09-01T15:49:16Z")

</div>

Is there a way to do this:

```julia-auto
c = combine(groupby(df, :A),:B => mean => :B_mean)

```

but in such a way that the output does not only show :A and :B\_mean but also the other variables that df had (well, at least the variables that can also be combined due to repetition)?

---

<div class="post-metadata">

**Author:** ![croberts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/croberts/32/9465_2.png) [@croberts](https://discourse.julialang.org/u/croberts)\
**Post date:** [September 1, 2026, 4:30pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/2 "2026-09-01T16:30:54Z")

</div>

DataFrames can’t know your intent beyond what you program. It can’t intuit which variables are invariant withing an “A” grouping unless you program that.

You could write:

```julia-auto
vars_sub = Symbol.(setdiff(names(df), ["B", "A"]) )
c = combine(groupby(df, :A), :B => mean => :B_mean, (vars_sub .=> first )...) 

```

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [September 1, 2026, 5:07pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/3 "2026-09-01T17:07:25Z")

</div>

You can just add all the variables that are constant within groups as extra grouping variables.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [September 1, 2026, 5:29pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/4 "2026-09-01T17:29:27Z")

</div>

```julia-auto
julia> using Statistics, StatsBase

julia> df = DataFrame(A = [1, 1, 2, 2], B = [1, 2, 300, 400], C = [5, 5, 6, 6], D = [10, 30, 60, 80])
4×4 DataFrame
 Row │ A B C D     
     │ Int64 Int64 Int64 Int64 
─────┼────────────────────────────
   1 │ 1 1 5 10
   2 │ 1 2 5 30
   3 │ 2 300 6 60
   4 │ 2 400 6 80

julia> function only_constant(x)
           all(==(first(x)), x) || throw(ArgumentError("All elements of the vector must be equal"))
           return first(x)
       end;

julia> @chain df begin
           @by :A begin
               :B = mean(:B)
               $([:C] .=> only_constant)
           end
       end
2×3 DataFrame
 Row │ A B C_only_constant 
     │ Int64 Float64 Int64           
─────┼─────────────────────────────────
   1 │ 1 1.5 5
   2 │ 2 350.0 6

```

---

<div class="post-metadata">

**Author:** ![mahmah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mahmah/32/214326_2.png) [@mahmah](https://discourse.julialang.org/u/mahmah)\
**Post date:** [September 1, 2026, 8:08pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/5 "2026-09-01T20:08:49Z")

</div>

Thanks for the great answers. I wonder whether there could be a shortcut for this. It’s probably not so rare that you have not only multiple factors and levels, but also multiple observations per subject and you want to group by ID and e.g. average some result.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [September 1, 2026, 8:08pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/6 "2026-09-01T20:08:50Z")

</div>

A variant of @croberts’ code:

```julia-auto
gdf = groupby(df, :A)
combine(gdf, :B => mean => :B_mean, Not([:A, :B]) .=> first)

```

---

<div class="post-metadata">

**Author:** ![mahmah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mahmah/32/214326_2.png) [@mahmah](https://discourse.julialang.org/u/mahmah)\
**Post date:** [September 1, 2026, 8:10pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/7 "2026-09-01T20:10:53Z")

</div>

@rafael.guerra ’s solution is the easiest to parse for newbies, but still bit hard to remember.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [September 1, 2026, 8:15pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/8 "2026-09-01T20:15:17Z")

</div>

In plain English, it reads: _For each column in the grouped dataframe (gdf), excluding the grouping variable (:A) and the aggregated column (:B), take the first value within each group._

---

<div class="post-metadata">

**Author:** ![eteppo](https://avatars.discourse-cdn.com/v4/letter/e/90db22/32.png) [@eteppo](https://discourse.julialang.org/u/eteppo)\
**Post date:** [September 2, 2026, 2:32pm UTC](https://discourse.julialang.org/t/combine-groupby/139142/9 "2026-09-02T14:32:35Z")

</div>

It could help to avoid redundancy in tabular data. In this case, you would have two datasets: one for person-level observations, and one for person-time -level observations. If you want to bring along more variables from the person-level table to the summary table, you join by ID. Example:

```julia-auto
julia> using DataFrames, Chain, Statistics

julia> person_df = DataFrame(id = [1,2,3], A = [1,0,0])
3×2 DataFrame
 Row │ id A     
     │ Int64 Int64 
─────┼──────────────
   1 │ 1 1
   2 │ 2 0
   3 │ 3 0

julia> person_time_df = DataFrame(id = [1,1,2,2,3,3], time = [1,2,1,2,1,2], B = [0,3,0,2,1,4])
6×3 DataFrame
 Row │ id time B     
     │ Int64 Int64 Int64 
─────┼─────────────────────
   1 │ 1 1 0
   2 │ 1 2 3
   3 │ 2 1 0
   4 │ 2 2 2
   5 │ 3 1 1
   6 │ 3 2 4

julia> mean_B_by_id = @chain person_time_df begin
           groupby(:id)
           combine(:B => mean => :mean_B)
       end
3×2 DataFrame
 Row │ id mean_B  
     │ Int64 Float64 
─────┼────────────────
   1 │ 1 1.5
   2 │ 2 1.0
   3 │ 3 2.5

julia> result = leftjoin(mean_B_by_id, person_df, on = :id)
3×3 DataFrame
 Row │ id mean_B A      
     │ Int64 Float64 Int64? 
─────┼────────────────────────
   1 │ 1 1.5 1
   2 │ 2 1.0 0
   3 │ 3 2.5 0

```
