tapply vs. aggregate in r

aggregate(bill_depth_mm ~ species + island,
          data = pg, mean)
#     species    island bill_depth_mm
# 1    Adelie    Biscoe      18.37045
# 2    Gentoo    Biscoe      14.98211
# 3    Adelie     Dream      18.25179
# 4 Chinstrap     Dream      18.42059
# 5    Adelie Torgersen      18.42941
tapply(pg$bill_depth_mm,
       list(pg$species, pg$island),
       mean, na.rm = T)
#             Biscoe    Dream Torgersen
# Adelie    18.37045 18.25179  18.42941
# Chinstrap       NA 18.42059        NA
# Gentoo    14.98211       NA        NA
aggregate(bill_depth_mm ~ species + island,
          data = pg, mean) %>% 
  pivot_wider(names_from = island,
    values_from = bill_depth_mm )
# # A tibble: 3 x 4
#   species   Biscoe Dream Torgersen
#   <fct>      <dbl> <dbl>     <dbl>
# 1 Adelie      18.4  18.3      18.4
# 2 Gentoo      15.0  NA        NA  
# 3 Chinstrap   NA    18.4      NA