# Combine rows but keep all columns

**URL:** <https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593>\
**Category:** Data\
**Tags:** dataframes\
**Created:** [November 13, 2024, 3:32pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593 "2024-11-13T15:32:53Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![slwu89](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/slwu89/32/217323_2.png) [@slwu89](https://discourse.julialang.org/u/slwu89)\
**Post date:** [November 13, 2024, 3:32pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/1 "2024-11-13T15:32:53Z")

</div>

Hi all, due to the lack of `copycalls` kwarg in `combine`, I am not sure if there is a more efficient way to achieve what I want to do.

The following code groups the example data frame by `ID` and then sums the values in `DataB` column together, and should return a single row per group, but with all columns preserved. Is there a better way to do this?

```julia
using DataFrames

mydf = DataFrame(
    ID=[:A,:A,:B,:C],
    DataA=[10,10,5,7],
    DataB=[12,63,4,5]
)

vcat([
    let 
        unique(transform(df, :DataB => sum => :DataB, copycols=true))
    end
    for df in groupby(mydf, :ID)
]...)

```

---

<div class="post-metadata">

**Author:** ![Rudi79](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rudi79/32/3884_2.png) [@Rudi79](https://discourse.julialang.org/u/Rudi79)\
**Post date:** [November 13, 2024, 4:50pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/2 "2024-11-13T16:50:42Z")

</div>

I would do

```julia
combine(groupby(mydf, :ID), :DataA => unique => :DataA, :DataB => sum => :DataB)

```

Of course, this only works if DataA has the same value for the corresponding ID.

---

<div class="post-metadata">

**Author:** ![slwu89](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/slwu89/32/217323_2.png) [@slwu89](https://discourse.julialang.org/u/slwu89)\
**Post date:** [November 13, 2024, 5:01pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/3 "2024-11-13T17:01:21Z")

</div>

Thank you! Is there some way to concisely specify `:DataA => unique => :DataA`, etc, for all the other columns? In my actual problem I have around 40 columns, which would be tedious to write out and modify if they change.

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [November 13, 2024, 5:13pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/4 "2024-11-13T17:13:10Z")

</div>

> [@slwu89](#):
>
> ```julia
> mydf = DataFrame(
> ID=[:A,:A,:B,:C],
> DataA=[10,10,5,7],
> DataB=[12,63,4,5]
> )
> 
> ```

```julia
combine(groupby(mydf, :ID), 1:ncol(mydf) .=> maximum, :DataB => sum)
3×5 DataFrame
 Row │ ID ID_maximum DataA_maximum DataB_maximum DataB_sum 
     │ Symbol Symbol Int64 Int64 Int64
─────┼─────────────────────────────────────────────────────────────
   1 │ A A 10 63 75
   2 │ B B 5 4 4
   3 │ C C 7 5 5

```

As for @Rudi79’s suggestion, this requires all the values of each column to be constant for each valie of ID.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [November 13, 2024, 5:23pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/5 "2024-11-13T17:23:22Z")

</div>

```julia
combine(groupby(mydf, [:ID,:DataA]), :DataB => sum => :DataB)

```

```julia
combine(groupby(mydf, Not(:DataB)), :DataB => sum => :DataB)

```

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [November 13, 2024, 5:29pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/6 "2024-11-13T17:29:27Z")

</div>

```julia
combine(groupby(mydf, propertynames(mydf)[1:ncol(mydf)-1]), :DataB => sum => :DataB)
3×3 DataFrame
 Row │ ID DataA DataB 
     │ Symbol Int64 Int64
─────┼──────────────────────
   1 │ A 10 75
   2 │ B 5 4
   3 │ C 7 5

```

Saves typing column names, but you need the “constant variables” all together in a block of columns, and the ones you want to apply the function to in a separate block.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [November 13, 2024, 5:31pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/7 "2024-11-13T17:31:09Z")

</div>

```julia
combine(groupby(mydf, :ID), Not([:ID,:DataB]).=>first.=>identity, :DataB => sum => :DataB)

combine(groupby(mydf, :ID), Not([:ID,:DataB]).=>Ref .=>identity, :DataB => sum => :DataB)

```

---

<div class="post-metadata">

**Author:** ![slwu89](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/slwu89/32/217323_2.png) [@slwu89](https://discourse.julialang.org/u/slwu89)\
**Post date:** [November 13, 2024, 7:56pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/8 "2024-11-13T19:56:27Z")

</div>

Thanks. I appreciate all the solutions but this one is extremely elegant.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [November 13, 2024, 8:19pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/9 "2024-11-13T20:19:16Z")

</div>

Another way to deal with possible non-uniqueness in groups is to error (which might be a good thing to catch such cases early). This can be done with:

```julia
combine(groupby(mydf, :ID), Not([:ID,:DataB]).=>only ∘ Set, :DataB => sum => :DataB)

```

(note using composition operator is not necessary, an anonymous function could do the same).

---

<div class="post-metadata">

**Author:** ![slwu89](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/slwu89/32/217323_2.png) [@slwu89](https://discourse.julialang.org/u/slwu89)\
**Post date:** [November 14, 2024, 9:42pm UTC](https://discourse.julialang.org/t/combine-rows-but-keep-all-columns/122593/10 "2024-11-14T21:42:54Z")

</div>

Cool, yes that’s a good idea. For some reason it never dawned on me to pass multiple functions to modify the columns.
