A conceptually simple question that I'm struggling with. I have observations ('Values') grouped by ID over time and want to normalize each observation to its previous observation. In the example below I can normalize each 'Value' to the first 'Time' observation within ID group (ie 10 to 10, 20 to 10, 30 to 10, etc) but I want to normalize each 'Value' to the previous observation (ie 20 to 10, 30 to 20, etc) and am having trouble getting it to work.
ID <- c(rep("A", 4), rep("B", 3), rep("C", 3))
Time <- c(10, 20, 30, 40, 10, 20, 30, 10, 20, 30)
Value <- sample(1:100, 10)
dat <- cbind(ID, Time, Value)
newDat <- dat %>%
arrange(Time) %>%
group_by(ID) %>%
mutate(ratio = Value/first(Value))
Use lag
to get previous value.
library(dplyr)
dat %>%
arrange(ID, Time) %>%
group_by(ID) %>%
mutate(ratio = Value/lag(Value))
# ID Time Value ratio
# <fct> <dbl> <int> <dbl>
# 1 A 10 53 NA
# 2 A 20 16 0.302
# 3 A 30 57 3.56
# 4 A 40 74 1.30
# 5 B 10 38 NA
# 6 B 20 54 1.42
# 7 B 30 61 1.13
# 8 C 10 78 NA
# 9 C 20 41 0.526
#10 C 30 83 2.02
We can also use head
and tail
dat %>%
arrange(ID, Time) %>%
group_by(ID) %>%
mutate(ratio = c(NA, tail(Value, -1)/head(Value, -1)))
data
ID <- c(rep("A", 4), rep("B", 3), rep("C", 3))
Time <- c(10, 20, 30, 40, 10, 20, 30, 10, 20, 30)
Value <- sample(1:100, 10)
dat <- data.frame(ID, Time, Value)
We can use data.table
methods
library(data.table)
setDT(df1)[order(Time), ratio := Value/shift(Value), ID]
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.