Reputation: 149
I am relatively new to R and sorry if the question was already asked but I obviously either can't understand the answers or can't find the right key words!
Here is my problem : I have a dataset that looks like that:
Name Year Corg
1 Bois 17 2001 1.7
2 Bois 17 2007 2.1
3 Bois 17 2014 1.9
4 8-Toume 2000 1.7
5 8-Toume 2015 1.4
6 7-Richelien 2 2004 1.1
7 7-Richelien 2 2017 1.5
8 7-Richelien 2 2019 1.2
9 Communaux 2003 1.4
10 Communaux 2016 3.8
11 Communaux 2019 2.4
12 Cocandes 2000 1.7
13 Cocandes 2014 2.1
As you can see, I sometimes have two or three rows of results per Name (theoretically I could even have 4, 5 or more rows per Name).
For each name, I would like to calculate the annual Corg rate of change between the highest year and lowest year.
More specificaly, I would like to do:
(Corg_of_highest_year/Corg_of_lowest_year)^(1/(lowest_year-highest_year))-1
Could you explain me how you would obtain a summarizing dataset that would look like that:
Name Length_in_years Corg_rate
Bois 17 13 0.9%
8-Toume 15 -1.3%
etc.
Upvotes: 2
Views: 85
Reputation: 1364
Here is a solution using data.table:
df = data.table(df)
mat = df[, .(
Rate = 100*((Corg[which.max(Year)] / Corg[which.min(Year)])^(1/diff(range(Year))) - 1)
), by = Name]
> mat
Name Rate
1: Bois17 0.8592524
2: 8-Toume -1.2860324
3: 7-Richelien2 0.5817615
4: Communaux 3.4261123
5: Cocandes 1.5207989
Upvotes: 0
Reputation: 388962
We can do the calculation using group_by
in dplyr
library(dplyr)
df %>%
group_by(Name) %>%
summarise(Length = diff(range(Year)),
Corg_rate = ((Corg[which.max(Year)]/Corg[which.min(Year)]) ^
(1/Length) - 1) * 100)
# A tibble: 5 x 3
# Name Length Corg_rate
# <fct> <int> <dbl>
#1 7-Richelien2 15 0.582
#2 8-Toume 15 -1.29
#3 Bois17 13 0.859
#4 Cocandes 14 1.52
#5 Communaux 16 3.43
To perform the analysis with most recent year and the year with minimum 5 years of difference
df %>%
group_by(Name) %>%
summarise(Length = max(Year) - max(Year[Year <= max(Year) - 5]),
Corg_rate = (Corg[which.max(Year)]/Corg[Year == max(Year[Year <= (max(Year) - 5)])]) ^ (1/Length) - 1,
Corg_rate = Corg_rate * 100)
# Name Length Corg_rate
# <fct> <int> <dbl>
#1 7-Richelien2 15 0.582
#2 8-Toume 15 -1.29
#3 Bois17 7 -1.42
#4 Cocandes 14 1.52
#5 Communaux 16 3.43
data
df <- structure(list(Name = structure(c(3L, 3L, 3L, 2L, 2L, 1L, 1L,
1L, 5L, 5L, 5L, 4L, 4L), .Label = c("7-Richelien2", "8-Toume",
"Bois17", "Cocandes", "Communaux"), class = "factor"), Year = c(2001L,
2007L, 2014L, 2000L, 2015L, 2004L, 2017L, 2019L, 2003L, 2016L,
2019L, 2000L, 2014L), Corg = c(1.7, 2.1, 1.9, 1.7, 1.4, 1.1,
1.5, 1.2, 1.4, 3.8, 2.4, 1.7, 2.1)), class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"))
Upvotes: 2
Reputation: 171
By first creating an indicator of when the year is max and min in group Name and then spreading the Corg column into MAX_Corg (Corg of the max year) and MIN_corg we can later easily calculate the rate of change.
my_df %>%
group_by(Name) %>%
mutate( #new column denoting the max and min
year_max_min = ifelse(Year == max(Year), "MAX_corg",
ifelse(Year == min(Year), "MIN_corg",
NA
)
)
) %>%
filter(!(is.na(year_max_min))) %>% # removing NA
group_by(Name, year_max_min) %>% #grouping by Name and max_min indicator
summarise(Corg= Corg) %>% #summarising
spread(year_max_min, Corg) %>% #spread the indicator into two column; MAX_corg and MIN_corg
mutate(
rate_of_change = (MAX_corg / MIN_corg)^(1/(MIN_corg - MAX_corg)) - 1 # calculates rate of change
)
Upvotes: 1
Reputation: 1177
Use dplyr
group_by(name) and then calculate your value. Here is an example
library(dplyr)
data %>%
group_by(name) %>%
summarise(Length = max(Year)-min(Year), Corg_End = sum(Corg[Year==max(Year), Corg_Start = sum(Corg[Year==min(Year)]))
This shows you the logic of grouping, i.e. after group_by(name) max(Year)
will give out the highest year per name instead of overall. Using this logic calculating the change rate should be easy but I won't attempt to try for lack of reproducible data.
Upvotes: 0