Skip to content

Conversation

@DavisVaughan
Copy link
Member

@DavisVaughan DavisVaughan commented Oct 7, 2025

Closes r-lib/vctrs#1935
Really closes #7024, which had become the vctrs issue because I thought the problem was there
Closes #7057

rbind(x, y) has a behavior where it retains the attributes of x exactly. It literally just uses an unclass()-ed x as the base object to start rbind-ing group. This means that any attributes of x that depend on the data will be wrong, like groups for us.

It's this value <- setting on the first iteration
https://github.com/wch/r-source/blob/8a1c36e93d8c72d4538f56bc59f5e780aac1a533/src/library/base/R/dataframe.R#L1331-L1332

library(dplyr)

x <- rowwise(tibble(a = 1:2))
y <- rowwise(tibble(a = 3:5))

out <- rbind(x, y)

# Looks fine at surface level
out
#> # A tibble: 5 × 1
#> # Rowwise: 
#>       a
#>   <int>
#> 1     1
#> 2     2
#> 3     3
#> 4     4
#> 5     5

# This is very wrong!
# It just copied over `"groups"` from `x`, the first input
attr(out, "groups")
#> # A tibble: 2 × 1
#>         .rows
#>   <list<int>>
#> 1         [1]
#> 2         [1]
attr(out, "groups")$.rows
#> <list_of<integer>[2]>
#> [[1]]
#> [1] 1
#> 
#> [[2]]
#> [1] 2

# Switch the order, now it comes from `y`
out <- rbind(y, x)
attr(out, "groups")
#> # A tibble: 3 × 1
#>         .rows
#>   <list<int>>
#> 1         [1]
#> 2         [1]
#> 3         [1]
attr(out, "groups")$.rows
#> <list_of<integer>[3]>
#> [[1]]
#> [1] 1
#> 
#> [[2]]
#> [1] 2
#> 
#> [[3]]
#> [1] 3

We already have rbind.grouped_df() for grouped data frames which just calls bind_rows(), so I'm now adding rbind.rowwise_df() which also just calls bind_rows(). That fixes the problem.

@DavisVaughan DavisVaughan merged commit 345a1dc into main Oct 10, 2025
12 checks passed
@DavisVaughan DavisVaughan deleted the fix/rbind-rowwise branch October 10, 2025 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants