I have an adjacency matrix that expresses feeding links between species (column eats row)
mat1<-matrix(data=c(0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0),
nrow=4,
ncol=4,
byrow = TRUE,
dimnames = list(c("a","b","c","d"),
c("a","b","c","d")))
I want to reduce the resolution of this matrix to family level using a dataframe that shows which family each species belongs to,
df <- data.frame(Species = c("a","b","c","d"), Family = c("E","E","F","F"))
so that the resulting matrix will give the number of feeding links between families
mat2<-matrix(data=c(0,2,1,0),
nrow=2,
ncol=2,
byrow = TRUE,
dimnames = list(c("E","F"),
c("E","F")))
Thank you for your time
Because it's the only way I know how, here's a solution using the tidyverse.
It turns the matrix into a long-form tibble, aggregates by family and then makes it wide again.
library(tidyverse)
# create a tibble that looks like the desired end-result matrix
df2 <- mat1 %>%
as_tibble(rownames = "Species_from") %>% # make a tibble
pivot_longer(cols = -Species_from,
names_to = "Species_to") %>% # turn into long form
left_join(df, by = c("Species_from" = "Species")) %>% # add Family_from and Family_to
left_join(df, by = c("Species_to" = "Species"), suffix = c("_from", "_to")) %>%
group_by(Family_from, Family_to) %>% # aggregate Family_from and Family_to
summarise(value = sum(value)) %>% # ... by taking their sum
pivot_wider(names_from = Family_to,
values_from = value) # turn back into wide form
# turn into a matrix
mat2 <- as.matrix(df2[, c("E", "F")])
rownames(mat2) <- df2$Family_from
mat2
# E F
# E 0 2
# F 1 0