根据唯一ID和日期将值计算为百分比变化

时间:2019-01-28 01:57:18

标签: r

我有一个重复测量的数据集,并用唯一的ID和日期标记。对于每个度量,我想创建一个数据帧,以针对每个唯一ID的所有后续度量计算从第一次度量起的百分比变化。 A的Jan 2,3和4值除以A的Jan 1值。在Excel中使用粘性公式非常容易做到这一点,但在R解决方案方面却步履维艰。

这是一个示例数据集:

values <- rnorm(12, 30, 5)
ID <- rep(c('A', 'B', 'C'), 4)
dates <- rep(as.Date(c("2019-01-01", "2019-01-02", "2019-01-03", "2019-01- 04")), 3)

dat <- data.frame(values, ID, dates)

     values ID      dates
  36.96190  A 2019-01-01
  22.44808  B 2019-01-01
  28.82219  C 2019-01-01
  18.50368  A 2019-01-02
  22.19817  B 2019-01-02
  33.77493  C 2019-01-02
  32.20991  A 2019-01-03
  28.80391  B 2019-01-03
  26.33285  C 2019-01-03
  31.87512  A 2019-01-04
  26.07043  B 2019-01-04
  22.17923  C 2019-01-04

1 个答案:

答案 0 :(得分:0)

我们可以使用dplyr轻松地做到这一点,首先要安排日期,然后将values除以first value按组(ID

library(dplyr)

dat %>%
  arrange(dates) %>%
  group_by(ID) %>%
  mutate(ratio = values/first(values))

OR

dat %>%
  arrange(dates) %>%
  group_by(ID) %>%
  mutate(ratio = values/values[1L])


#   values ID    dates      ratio
#    <dbl> <fct> <date>     <dbl>
# 1   24.0 A     2019-01-01 1    
# 2   32.1 B     2019-01-01 1    
# 3   27.2 C     2019-01-01 1    
# 4   31.4 B     2019-01-02 0.976
# 5   32.5 C     2019-01-02 1.20 
# 6   25.5 A     2019-01-02 1.07 
# 7   35.4 C     2019-01-03 1.30 
# 8   27.1 A     2019-01-03 1.13 
# 9   27.6 B     2019-01-03 0.859
#10   18.3 A     2019-01-04 0.762
#11   27.3 B     2019-01-04 0.848
#12   25.0 C     2019-01-04 0.920

使用ave的基本R方法,这里我们获得每个ID的最小行索引,然后将相应的values除以组中的values。 / p>

dat$ratio <- with(dat, values/values[ave(order(dates), ID, FUN = min)])

dat
#     values ID      dates     ratio
#1  23.96467  A 2019-01-01 1.0000000
#2  31.38715  B 2019-01-02 0.9764050
#3  35.42221  C 2019-01-03 1.3033536
#4  18.27151  A 2019-01-04 0.7624353
#5  32.14562  B 2019-01-01 1.0000000
#6  32.53028  C 2019-01-02 1.1969457
#7  27.12630  A 2019-01-03 1.1319287
#8  27.26684  B 2019-01-04 0.8482287
#9  27.17774  C 2019-01-01 1.0000000
#10 25.54981  A 2019-01-02 1.0661449
#11 27.61404  B 2019-01-03 0.8590294
#12 25.00807  C 2019-01-04 0.9201673

数据

set.seed(1234)
values <- rnorm(12, 30, 5)
ID <- rep(c('A', 'B', 'C'), 4)
dates <- rep(as.Date(c("2019-01-01", "2019-01-02", "2019-01-03", "2019-01- 04")), 3)
dat <- data.frame(values, ID, dates)