Reputation: 13
I have a data frame with 66 species with 3 years of relative abundance an I want to do a graph in R with ggplot2 to show the abundance of each year for each species. The problem is that to do a graph like that I need a different shape of my data frame and I can't find the code to change it.
So, my data frame is:
Species 2016 2017 2018
Sp1 4 8 3
Sp2 0 0 1
Sp3 6 4 8
Sp4 7 5 5
...
The data frame that I need for the graph should have the following shape:
Year Abundance
Sp1 2016 4
Sp1 2017 8
Sp1 2018 3
Sp2 2016 0
Sp2 2017 0
Sp2 2018 1
Sp3 2016 6
...
I am sure there is a way, there is always a way, but I can't find it :(
Upvotes: 1
Views: 54
Reputation: 1599
With tidyr
+ dplyr
.
library(tidyr)
library(dplyr)
df <- df %>%
tidyr::gather(key = "Year", value = "Abudance", -Species)
df
> df
Species Year Abudance
1 sp1 2016 4
2 sp2 2016 0
3 sp3 2016 6
4 sp4 2016 7
5 sp1 2017 8
6 sp2 2017 0
7 sp3 2017 4
8 sp4 2017 5
9 sp1 2018 3
10 sp2 2018 1
11 sp3 2018 8
12 sp4 2018 5
As noted by @gersht, it is not absolutely necessary to use the dplyr
package for this answer, I usually use dplyr
in order to make reading the code more fluid.
library(tidyr)
df <- tidyr::gather(df, key = "Year", value = "Abudance", -Species)
Another possibility of stacking information is to use the function melt
of the reshape2
package. I inform you that this package is retired, however, sometimes, I still use it.
library(dplyr)
library(reshape2)
df <- df %>%
reshape2::melt(id.vars = "Species", value.name = "Abundance", variable.name = "Year")
##
## Or only reshape2
df3 <- reshape2::melt(df, id.vars = "Species", value.name = "Abundance", variable.name = "Year")
Or by using command residing in the R, without packet aid.
# Columns to be maintained
column <- c("Species")
dfx <- utils::stack(df, select = -Species)
dfx[, column] <- rep(df$Species, (ncol(df) - length(column)))
colnames(dfx) <- c("Abundance", "Year", column)
dfx <- dfx[, c(3,2,1)]
df <- data.frame(Species = c("sp1", "sp2", "sp3", "sp4"),
"2016" = c(4,0,6,7),
"2017" = c(8,0,4,5),
"2018" = c(3,1,8,5), check.names = F)
Upvotes: 2