Giulia
Giulia

Reputation: 13

Changing a table to use it in for a graph

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

Answers (1)

bbiasi
bbiasi

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)]

Data

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

Related Questions