1

这是我的数据示例:

           id   score
1          82   0.50000
2          82   0.39286
3          82   0.56250
4         328   0.50000
5         328   0.67647
6         328   0.93750
7         328   0.91667

我想为每个 id 制作一列移动平均分数。

所以我需要以某种方式按 id 对数据进行分组,然后将 MA 函数应用于该分组数据,然后将输出作为另一列“MA_score”

我希望我的输出看起来像这样:

           id   score    MA_score
1          82   0.50000   NULL
2          82   0.39286   0.xxxx
3          82   0.56250   NULL
4         328   0.50000   NULL
5         328   0.67647   0.yyyy
6         328   0.93750   0.qqqq
7         328   0.91667   NULL
4

2 回答 2

4

您可以使用 zoo 包中的 split 和 rollapply 作为解决此问题的众多方法之一。请注意,在下面的示例中,我将 rollapply 函数的宽度设置为 1,因此它只返回每个值。对于大于 1 的宽度,它将采用该值的平均值。

require(zoo)
sapply( split( df , df$id) , function(x) rollapply( x , width = 1 , align = 'left' , mean) )
#Note that by setting width = 1 we just return the value
$`82`
     id   score
[1,] 82 0.50000
[2,] 82 0.39286
[3,] 82 0.56250

$`328`
      id   score
[1,] 328 0.50000
[2,] 328 0.67647
[3,] 328 0.93750
[4,] 328 0.91667

如果我们设置width = 3你会得到:

$`82`
     id   score
[1,] 82 0.48512

$`328`
      id     score
[1,] 328 0.7046567
[2,] 328 0.8435467

base或者你可以在R中使用聚合:

aggregate(  score ~ id , data = df , function(x) rollapply( x , width = 1 , align = 'left' , mean)  )
   id                              score
1  82          0.50000, 0.39286, 0.56250
2 328 0.50000, 0.67647, 0.93750, 0.91667

有很多方法可以做到这一点。不过,我会精确定义您的移动平均函数,因为有很多方法可以计算它(例如查看TTR:::SMA


或者更直接地使用ave

within(df, { MA_score <- ave(score, id, FUN=function(x) 
                rollmean(x, k=3, na.pad = TRUE))})
于 2013-04-16T13:11:35.547 回答
2

您可以按唯一 ID 值拆分数据,计算每个唯一 ID 的滚动平均值(来自“zoo”包)并将结果附加到初始数据帧:

# Required packages
library(zoo)

# Data setup
df <- data.frame(id = c(82, 82, 82, 328, 328, 328, 328), 
                 score = c(0.5, 0.39286, 0.5625, 0.5, 0.67647, 0.9375, 0.91667))

# Split data by unique IDs
df.sp <- split(df, df$id)

# Calculate rolling mean for each unique ID
df.ma <- lapply(seq(df.sp), function(i) {
  rollmean(df.sp[[i]]$score, k = 3, na.pad = TRUE)
})

# Append column 'MA_score' to dataframe
for (i in seq(names(df.sp))) {
  df[which(df$id == names(df.sp)[i]), "MA_score"] <- df.ma[[i]]
}

df
   id   score  MA_score
1  82 0.50000        NA
2  82 0.39286 0.4851200
3  82 0.56250        NA
4 328 0.50000        NA
5 328 0.67647 0.7046567
6 328 0.93750 0.8435467
7 328 0.91667        NA
于 2013-04-16T13:25:38.957 回答