Мы можем преобразовать в 'длинный' формат, получить 'count' и затем преобразовать в 'wide'
library(dplyr)
library(tidyr)
df1 %>%
pivot_longer(cols = -ID) %>%
count(ID, value) %>%
pivot_wider(names_from = value, values_from = n, values_fill = list(n = 0))
# A tibble: 7 x 8
# ID A01 A02 A07 A03 A08 A103 A09
# <int> <int> <int> <int> <int> <int> <int> <int>
#1 1 1 1 0 0 0 0 0
#2 2 1 0 1 0 0 0 0
#3 3 0 0 0 1 1 0 0
#4 4 1 0 0 0 0 1 0
#5 5 0 0 0 0 1 0 1
#6 6 0 2 0 0 0 0 0
#7 7 0 0 0 0 2 0 0
или table
из base R
table(rep(df1$ID, 2), unlist(df1[-1]))
Или с recast
из reshape2
library(reshape2)
recast(df1, id.var = 'ID', ID ~ value, length)
data
df1 <- structure(list(ID = 1:7, allele_1 = c("A01", "A01", "A08", "A103",
"A09", "A02", "A08"), allele_2 = c("A02", "A07", "A03", "A01",
"A08", "A02", "A08")), class = "data.frame", row.names = c(NA,
-7L))