Looks like you have
df
#   id antibiotic antibiotic_date
# 1  1          a      2018-01-20
# 2  1          b      2018-01-20
# 3  1          c      2018-03-04
Use unique in aggregate.
(res1 <- aggregate(. ~ antibiotic_date, df, unique))
#   antibiotic_date id antibiotic
# 1      2018-01-20  1       a, b
# 2      2018-03-04  1          c
Where
str(res1)
# 'data.frame': 2 obs. of  3 variables:
# $ antibiotic_date: chr  "2018-01-20" "2018-03-04"
# $ id             : chr  "1" "1"
# $ antibiotic     :List of 2
# ..$ : chr  "a" "b"
# ..$ : chr "c"
If you need a string rather than a vector of length > 1 make it toString,
(res2 <- aggregate(. ~ antibiotic_date, df, \(x) toString(unique(x))))
#   antibiotic_date id antibiotic
# 1      2018-01-20  1       a, b
# 2      2018-03-04  1          c
where:
str(res2)
# 'data.frame': 2 obs. of  3 variables:
# $ antibiotic_date: chr  "2018-01-20" "2018-03-04"
# $ id             : chr  "1" "1"
# $ antibiotic     : chr  "a, b" "c"
Or paste,
(res3 <- aggregate(. ~ antibiotic_date, df, \(x) paste(unique(x), collapse=' ')))
#   antibiotic_date id antibiotic
# 1      2018-01-20  1        a b
# 2      2018-03-04  1          c
where:
str(res3)
# 'data.frame': 2 obs. of  3 variables:
# $ antibiotic_date: chr  "2018-01-20" "2018-03-04"
# $ id             : chr  "1" "1"
# $ antibiotic     : chr  "a b" "c"
You can also wrap a sort around it, if needed, e.g. sort(toString(unique(.))).
Data:
df <- structure(list(id = c(1, 1, 1), antibiotic = c("a", "b", "c"), 
    antibiotic_date = c("2018-01-20", "2018-01-20", "2018-03-04"
    )), class = "data.frame", row.names = c(NA, -3L))