Setup.

library(tidyverse)
## -- Attaching packages ------------------------------------------ tidyverse 1.2.1 --
## v ggplot2 3.0.0     v purrr   0.2.5
## v tibble  1.4.2     v dplyr   0.7.6
## v tidyr   0.8.1     v stringr 1.3.1
## v readr   1.1.1     v forcats 0.3.0
## -- Conflicts --------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()

Data.

dataset <- tibble::tribble(
  ~site,  ~sp, ~status,
    "a", "sp1",    "A",
    "a", "sp1",    "D",
    "a", "sp1",    "A",
    "b", "sp1",    "A",
    "b", "sp2",    "D",
    "b", "sp3",    "A"
)
dataset
## # A tibble: 6 x 3
##   site  sp    status
##   <chr> <chr> <chr> 
## 1 a     sp1   A     
## 2 a     sp1   D     
## 3 a     sp1   A     
## 4 b     sp1   A     
## 5 b     sp2   D     
## 6 b     sp3   A

Create an interaction variable to “dodge manually”.

dodge <- mutate(dataset, site_sp = interaction(site, sp))
dodge
## # A tibble: 6 x 4
##   site  sp    status site_sp
##   <chr> <chr> <chr>  <fct>  
## 1 a     sp1   A      a.sp1  
## 2 a     sp1   D      a.sp1  
## 3 a     sp1   A      a.sp1  
## 4 b     sp1   A      b.sp1  
## 5 b     sp2   D      b.sp2  
## 6 b     sp3   A      b.sp3

Count.

dodge <- add_count(dodge, site_sp)

Plot.

ggplot(dodge, aes(x = site_sp, y = n, fill = status)) +
  geom_col()