如何计算数据框中每个人的前 7 个观察值的平均值

How to calculate the average of the first 7 observations per individual in a data frame

我有一个结构如下的数据框

>data
  ID  Location Sex   Time  Var1  Var2  Var3  Var4  Var5  Var6
   12     A     M     .1    …      …     …     …     …     … 
   12     A     M     .2    …      …     …     …     …     … 
   12     A     M     .3    …      …     …     …     …     … 
   12     A     M     .4    …      …     …     …     …     …
   12     A     M     .5    …      …     …     …     …     … 
   12     A     M     .6    …      …     …     …     …     … 
   234    A     M     .1    …      …     …     …     …     … 
   234    A     M     .2    …      …     …     …     …     … 
   234    A     M     .3    …      …     …     …     …     … 
   234    A     M     .4    …      …     …     …     …     … 
   234    A     M     .5    …      …     …     …     …     …  

有数百个人,每个人都有一个唯一的 ID 号码。每个人的数据是时间序列数据。在真实数据中,每个人有数百个测量值。例如,在上面的示例中,个体 12 只有 6 个观察值,个体 234 有 5 个观察值。实际上,个体 12 可能有 980 个观察值,个体 234 可能有 1249 个观察值。

如何将 R 转换为 return 数据框,其中每个人的前 7 个观察值的平均值采用这种格式:

ID  Location  Sex  Variable  Average
12     A        M      Var1     … 
12     A        M      Var2     … 
12     A        M      Var3     … 
12     A        M      Var4     … 
12     A        M      Var5     … 
12     A        M      Var6     … 
234    A        M      Var1     … 
234    A        M      Var2     … 
234    A        M      Var3     … 
234    A        M      Var4     … 
234    A        M      Var5     … 
234    A        M      Var6     … 

我怎样才能对每个人的最后 7 个观察结果做同样的事情(记住每个人的时间序列长度不同)

使用 dplyr,您应该能够调整 data.frame 以将所有观察结果放在一个列中,过滤每个 ID 和变量的前 7 个时间,然后取平均值.

library(dplyr)
library(readr) ## just to read OP's data

df <- readr::read_table("  ID   Location Sex   Time  Var1  Var2  Var3  Var4  Var5  Var6
   12     A     M     .1    a      a     a     a     a     a 
   12     A     M     .2    a      a     a     a     a     a 
   12     A     M     .3    a      a     a     a     a     a 
   12     A     M     .4    a      a     a     a     a     a
   12     A     M     .5    a      a     a     a     a     a 
   12     A     M     .6    a      a     a     a     a     a 
   234    A     M     .1    a      a     a     a     a     a 
   234    A     M     .2    a      a     a     a     a     a 
   234    A     M     .3    a      a     a     a     a     a 
   234    A     M     .4    a      a     a     a     a     a 
   234    A     M     .5    a      a     a     a     a     a ") %>%
  mutate_at(vars(contains("Var")), ~runif(11))

df %>%
  pivot_longer(contains("Var"), names_to = "Variable") %>%
  group_by(ID, Location, Sex, Variable) %>%
  top_n(7, desc(Time)) %>%
  summarize(Average = mean(value))
#> # A tibble: 12 x 5
#> # Groups:   ID, Location, Sex [2]
#>       ID Location Sex   Variable Average
#>    <dbl> <chr>    <chr> <chr>      <dbl>
#>  1    12 A        M     Var1       0.356
#>  2    12 A        M     Var2       0.528
#>  3    12 A        M     Var3       0.489
#>  4    12 A        M     Var4       0.613
#>  5    12 A        M     Var5       0.557
#>  6    12 A        M     Var6       0.730
#>  7   234 A        M     Var1       0.365
#>  8   234 A        M     Var2       0.557
#>  9   234 A        M     Var3       0.580
#> 10   234 A        M     Var4       0.626
#> 11   234 A        M     Var5       0.344
#> 12   234 A        M     Var6       0.534

最后 7 个,你所要做的就是将 top_n(7, desc(Time) 行更改为 top_n(7, Time),以便将最高值排列到最低值。

您可以使用 aggregate/reshape 方法。

res <- reshape(aggregate(. ~ id + location + sex, data=dat, function(x) 
  mean(x[1:7]))[-4], varying=4:9, idvar=1:3, direction="long", sep="")
res[order(res$id), ]  # just a little order
#            id location sex time         var
# 12.A.M.1   12        A   M    1  0.23035482
# 12.A.M.2   12        A   M    2  0.67700690
# 12.A.M.3   12        A   M    3  0.12926876
# 12.A.M.4   12        A   M    4  0.06464387
# 12.A.M.5   12        A   M    5 -0.39031674
# 12.A.M.6   12        A   M    6 -0.21768911
# 234.A.M.1 234        A   M    1  0.17089758
# 234.A.M.2 234        A   M    2 -0.09195034
# 234.A.M.3 234        A   M    3  0.40042572
# 234.A.M.4 234        A   M    4  0.23404603
# 234.A.M.5 234        A   M    5  0.08176435
# 234.A.M.6 234        A   M    6  0.02859807

或使用by

do.call(rbind, by(dat, dat$id, function(x) {
    cbind(x[1:6, 1:3], var=names(x[5:10]), mn=colMeans(x[1:7, 5:10]))
}))
#         id location sex  var          mn
# 12.1    12        A   M var1  0.23035482
# 12.3    12        A   M var2  0.67700690
# 12.5    12        A   M var3  0.12926876
# 12.7    12        A   M var4  0.06464387
# 12.9    12        A   M var5 -0.39031674
# 12.11   12        A   M var6 -0.21768911
# 234.2  234        A   M var1  0.17089758
# 234.4  234        A   M var2 -0.09195034
# 234.6  234        A   M var3  0.40042572
# 234.8  234        A   M var4  0.23404603
# 234.10 234        A   M var5  0.08176435
# 234.12 234        A   M var6  0.02859807

数据:

set.seed(42)
dat <- expand.grid(id=c(12, 234), location="A", sex="M", time=(1:20)/10)
dat <- cbind(dat, matrix(rnorm(240), 40, 6, dimnames=list(NULL, paste0("var", 1:6))))
dat <- dat[order(dat$id), ]