简体   繁体   中英

Growth rate of time-series data in R

library(ggplot2)
library(data.table)

set.seed(100)

# Making data table
date <- rep(1:10, each=10)
id <- rep(1:10, 10)
grp <- rep(1:2, each=5)

# Adding random body size per group and averaging
dt <- as.data.table(cbind(date, grp, id))
dt[grp==1, bodysize:=rnorm(50, mean=6)]
dt[grp==2, bodysize:=rnorm(50, mean=7)]
dt <- dt[, mean.Body:=mean(bodysize), list(date, grp)]

# Plot
ggplot(data=dt, aes(x=date, y=mean.Body, group=grp)) + 
  geom_line(position="identity", aes(color=as.factor(grp)), size= 2, linetype= 2) +
  geom_point(size=2) +
  theme_minimal() + 
  labs(x= "Date", y= "Body size (mm)", color="Group" )

体型随时间变化

My question is how to implement a function to calculate the growth rate over several days for individuals in a data table. This is morphological data, so growth rate will be calculated as log(body size day(i)) - log(body size day (i-1)). In other words, (body size today) - (body size yesterday). I have 5 individuals per group for 10 days. Finding the growth rate per day for each individual is the goal of this post and to recreate the graph posted but for growth rate per day. Attached is some mock data.

Any suggestions will be greatly appreciated.

Okay, I'm no good at data.table , but here's an attempt in tidyverse .

First, I'll remake your data.

library(tidyverse)

set.seed(100)

# Making data
date <- rep(1:10, each=10)
id <- rep(1:10, 10)
grp <- rep(1:2, each=5)

df <- cbind(date, grp, id) %>% 
  as_tibble %>%
  rowwise %>%
  mutate(bodysize = rnorm(1, mean = 5 + grp)) %>%
  ungroup

I couldn't come up with a better solution than doing a pivot_wider , doing the lag by individual, and the pivoting back to long format, in order to get the lag to work properly:

result <- df %>% 
  pivot_wider(names_from = c(grp, id), 
              values_from = bodysize) %>%
  mutate_at(vars(-date), 
            list(growth = ~. - lag(.))) %>%
  pivot_longer(-date, names_to = c("grp", "id"), 
               names_pattern = "([0-9]+)_([0-9]+)",
               values_to = "growth") %>%
  filter(!is.na(growth))

Now, I'm a little unsure about what your desired plot is. You mentioned 5 individuals, but you have 10 ids. If we plot them each, the plot gets a little messy, but you could play around with aes to separate each line.

# Plot
ggplot(result, 
       aes(x = date, y = growth, group = id)) + 
  geom_line(position = "identity", 
            aes(color = as.factor(grp)), size = 2, linetype = 2) +
  geom_point(size = 2) +
  theme_minimal() + 
  labs(x = "Date", y = "Body size (mm)", color = "Group" )

Alternatively, we can of course average per group over each id to get a neater plot, if that's what you prefer:

# Alternative plot
ggplot(result %>% group_by(date, grp) %>% summarise(grp_mean = mean(growth)), 
       aes(x = date, y = grp_mean, group = grp)) + 
  geom_line(position = "identity", 
            aes(color = as.factor(grp)), size = 2, linetype = 2) +
  geom_point(size = 2) +
  theme_minimal() + 
  labs(x = "Date", y = "Body size (mm)", color = "Group")

Created on 2019-12-06 by the reprex package (v0.2.1)

(Completely edited for a better attempt.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM