I'm afraid its not so simply to say you want all rows in a dataframe that have a unique id number, because you are not proposing an explicit method of choosing which accompanying data to show along with the unique id, should it be the first entry, the last, or should it be an aggregation, like the max or the min or the average of the other values.
Here are some examples of picking the row based on an order approach.
I'll start by taking the example df, and make a df2 which a 'rn' variable to hold the position of the row from the perspective of the col3 group.
Then I show how to take top or bottom
df <- tribble(~col1, ~col2, ~col3,
"X", "A", 1,
"Y", "B", 2,
"X", "B", 2,
"Y", "C", 3,
"Z", "B", 3,
"Z", "C", 4)
df2 <- df %>%
group_by(col3) %>%
mutate(rn = row_number())
df2
# A tibble: 6 x 4
# Groups: col3 [4]
col1 col2 col3 rn
<chr> <chr> <dbl> <int>
1 X A 1 1
2 Y B 2 1
3 X B 2 2
4 Y C 3 1
5 Z B 3 2
6 Z C 4 1
df2%>%
top_n(n = -1)
#Selecting by rn
# A tibble: 4 x 4
# Groups: col3 [4]
col1 col2 col3 rn
<chr> <chr> <dbl> <int>
1 X A 1 1
2 Y B 2 1
3 Y C 3 1
4 Z C 4 1
df2%>%
top_n(n = 1)
#Selecting by rn
# A tibble: 4 x 4
# Groups: col3 [4]
col1 col2 col3 rn
<chr> <chr> <dbl> <int>
1 X A 1 1
2 X B 2 2
3 Z B 3 2
4 Z C 4 1