R移动平均线

R moving average

作为示例,我使用具有 3 列(id(已添加)、medv、lstat)和 506 个观察值的 Boston 数据。

我想计算变量 medv 的 k-1 个观测值的移动平均值。这意味着应该计算除特定行之外的所有观察值的平均值。对于 id 1,从第 2-506 行计算平均值。对于 id 2,平均值是通过第 1 + 3-506 行计算的。对于 id 3,平均值是在 1-2 + 4-506 等行上计算的。

在第二步中,平均值的计算应该是有条件的,例如在两个不同的列中高于中位数和低于中位数。这意味着我们首先检查每列(medv 和 lstat)中的值是高于还是低于中位数。如果 medv 中的值高于中位数,我们根据 lstat 中高于中位数的值计算 lstat 的平均值。如果 medv 中的值低于中值,我们根据低于中值的值计算 lstat 的平均值。有关前 10 行,请参见下面的示例 table。前 10 行的中值对于 medv 是 25.55,对于 lstat 是 7.24。

这是数据:

library(mlbench)
data(BostonHousing)
df <- BostonHousing
df$id <- seq.int(nrow(df))
df <- subset(df, select = c(id, medv, lstat))
id medv lstat mean1out meancond
 1 24.0  4.98 26.66667     4.50
 2 21.6  9.14 26.93333     4.50
 3 34.7  4.03 25.47778    17.55
 4 33.4  2.94 25.62222    17.55
 5 36.2  5.33 25.31111    17.55
 6 28.7  5.21 26.14444    17.55
 7 22.9 12.43 26.78889     4.50
 8 27.1 19.15 26.32222    17.55
 9 16.5 29.93 27.50000     4.50
10 18.9 17.10 27.23333     4.50
mean(dat$medv[-3])
# [1] 25.47778

sapply(seq_len(nrow(dat)), function(i) mean(dat$medv[-i]))
#  [1] 26.66667 26.93333 25.47778 25.62222 25.31111 26.14444 26.78889 26.32222 27.50000 27.23333

或者(在数学上),没有 sapply,你可以这样得到相同的数字:

n <- nrow(dat)
(mean(dat$medv)*n - dat$medv)/(n-1)
#  [1] 26.66667 26.93333 25.47778 25.62222 25.31111 26.14444 26.78889 26.32222 27.50000 27.23333

对于您的条件平均值,一个简单的 ifelse 有效:

n <- nrow(dat)
transform(
  dat,
  a = (mean(dat$medv)*n - dat$medv)/(n-1),
  b = ifelse(medv <= median(medv),
             mean(lstat[ lstat <= median(lstat) ]),
             mean(lstat[ lstat > median(lstat) ]))
)
#    id medv lstat mean1out meancond        a      b
# 1   1 24.0  4.98 26.66667     4.50 26.66667  4.498
# 2   2 21.6  9.14 26.93333     4.50 26.93333  4.498
# 3   3 34.7  4.03 25.47778    17.55 25.47778 17.550
# 4   4 33.4  2.94 25.62222    17.55 25.62222 17.550
# 5   5 36.2  5.33 25.31111    17.55 25.31111 17.550
# 6   6 28.7  5.21 26.14444    17.55 26.14444 17.550
# 7   7 22.9 12.43 26.78889     4.50 26.78889  4.498
# 8   8 27.1 19.15 26.32222    17.55 26.32222 17.550
# 9   9 16.5 29.93 27.50000     4.50 27.50000  4.498
# 10 10 18.9 17.10 27.23333     4.50 27.23333  4.498

(我推断差异是数据输入时的舍入误差。)

问题的第一部分已经被@r2evans 解决了。

对于第二部分,我们可以计算lstatmedvmedian,比较并赋值。

#First part from @r2evans answer. 
n <- nrow(df)
df$mean1out <- (mean(df$medv)*n - df$medv)/(n-1)


#Second part
med_lsat <- median(df$lstat)
med_medv <- median(df$medv)
higher_lsat <- mean(df$lstat[df$lstat > med_lsat])
lower_lsat <- mean(df$lstat[df$lstat < med_lsat])
df$meancond <- ifelse(df$medv > med_medv, higher_lsat, lower_lsat)
df

#   id medv lstat mean1out meancond
#1   1 24.0  4.98 26.66667    4.498
#2   2 21.6  9.14 26.93333    4.498
#3   3 34.7  4.03 25.47778   17.550
#4   4 33.4  2.94 25.62222   17.550
#5   5 36.2  5.33 25.31111   17.550
#6   6 28.7  5.21 26.14444   17.550
#7   7 22.9 12.43 26.78889    4.498
#8   8 27.1 19.15 26.32222   17.550
#9   9 16.5 29.93 27.50000    4.498
#10 10 18.9 17.10 27.23333    4.498

数据

df <- BostonHousing
df$id <- seq.int(nrow(df))
df <- subset(df, select = c(id, medv, lstat))
df <- head(df, 10)