为每个数据帧列计算每行的三个后续行数据的平均值 (R)
Computing for each datafram column the mean of three subsequent row data for each row (R)
首先,针对我的问题的简单 R 示例:
> df
x y
1 1 3
2 2 7
3 4 9
4 8 0
5 3 1
6 12 24
我想为每一列计算每一行的三个后续行数据的平均值,结果为以下数据框。
> dfRes
xRes yRes
x y
1 2.333333 6.333333
2 4.666667 5.333333
3 5.000000 3.333333
4 7.666667 8.333333
5 NA NA
6 NA NA
因为我有很多列和行的非常大的数据框,所以我想避免在这个计算中使用 for 循环。我尝试定义自定义函数以使用可用的 sapply
函数。
有人知道 R 中这个问题的计算时间相对较快的简单解决方案吗?
----更新----
计算过程应该是这样的:
xRes[1] = mean(x[1] + x[2] + x[3])
xRes[2] = mean(x[2] + x[3] + x[4])
...
xRes[5] = NA # because there is no x[7]
地图功能怎么样? https://www.rdocumentation.org/packages/purrr/versions/0.2.5/topics/map
它实际上是 for-loop
的一个很好的替代品
我将转换矩阵中的数据框并将 colMeans 与 nrow 参数一起使用。
解决方案基本上是从这里的这个答案复制而来的:
# devtools::install_github("alistaire47/read.so")
foo <- read.so::read.so(
"
x y
1 1 3
2 2 7
3 4 9
4 8 0
5 3 1
6 12 24")
foo_mat <- as.matrix(foo)
sapply(foo, function(x) colMeans(matrix(x, nrow = 3)))
#> x y
#> [1,] 2.333333 6.333333
#> [2,] 7.666667 8.333333
这取决于长度(矩阵)是 (3) 的倍数。在另一个 post 中,我链接到一个显然处理其他情况的解决方案
您可以使用具有适当 window 大小的滚动函数。
df[] <- lapply(df, zoo::rollmean, 3, fill = NA, align = 'left')
如果您的数据量很大,使用 data.table
可能会有所帮助。
library(data.table)
setDT(df)[, lapply(.SD, frollmean, 3, align = 'left')]
在this historic answer的基础上使用filter
。
n <- 3
df1[] <- lapply(df1, function(x) c(na.omit(filter(x, rep(1 / n, n))), rep(NA, n - 1)))
df1
# x y
# 1 2.333333 6.333333
# 2 4.666667 5.333333
# 3 5.000000 3.333333
# 4 7.666667 8.333333
# 5 NA NA
# 6 NA NA
数据:
df1 <- structure(list(x = c(2.33333333333333, 4.66666666666667, 5, 7.66666666666667,
NA, NA), y = c(6.33333333333333, 5.33333333333333, 3.33333333333333,
8.33333333333333, NA, NA)), row.names = c("1", "2", "3", "4",
"5", "6"), class = "data.frame")
使用 lag
、lead
和 mutate
来自 dplyr
df%>%
mutate(x=(lag(x,0)+lead(x)+lead(x,2))/3 , y=(lag(y,0)+lead(y)+lead(y,2))/3)
首先,针对我的问题的简单 R 示例:
> df
x y
1 1 3
2 2 7
3 4 9
4 8 0
5 3 1
6 12 24
我想为每一列计算每一行的三个后续行数据的平均值,结果为以下数据框。
> dfRes
xRes yRes
x y
1 2.333333 6.333333
2 4.666667 5.333333
3 5.000000 3.333333
4 7.666667 8.333333
5 NA NA
6 NA NA
因为我有很多列和行的非常大的数据框,所以我想避免在这个计算中使用 for 循环。我尝试定义自定义函数以使用可用的 sapply
函数。
有人知道 R 中这个问题的计算时间相对较快的简单解决方案吗?
----更新---- 计算过程应该是这样的:
xRes[1] = mean(x[1] + x[2] + x[3])
xRes[2] = mean(x[2] + x[3] + x[4])
...
xRes[5] = NA # because there is no x[7]
地图功能怎么样? https://www.rdocumentation.org/packages/purrr/versions/0.2.5/topics/map 它实际上是 for-loop
的一个很好的替代品我将转换矩阵中的数据框并将 colMeans 与 nrow 参数一起使用。 解决方案基本上是从这里的这个答案复制而来的:
# devtools::install_github("alistaire47/read.so")
foo <- read.so::read.so(
"
x y
1 1 3
2 2 7
3 4 9
4 8 0
5 3 1
6 12 24")
foo_mat <- as.matrix(foo)
sapply(foo, function(x) colMeans(matrix(x, nrow = 3)))
#> x y
#> [1,] 2.333333 6.333333
#> [2,] 7.666667 8.333333
这取决于长度(矩阵)是 (3) 的倍数。在另一个 post 中,我链接到一个显然处理其他情况的解决方案
您可以使用具有适当 window 大小的滚动函数。
df[] <- lapply(df, zoo::rollmean, 3, fill = NA, align = 'left')
如果您的数据量很大,使用 data.table
可能会有所帮助。
library(data.table)
setDT(df)[, lapply(.SD, frollmean, 3, align = 'left')]
在this historic answer的基础上使用filter
。
n <- 3
df1[] <- lapply(df1, function(x) c(na.omit(filter(x, rep(1 / n, n))), rep(NA, n - 1)))
df1
# x y
# 1 2.333333 6.333333
# 2 4.666667 5.333333
# 3 5.000000 3.333333
# 4 7.666667 8.333333
# 5 NA NA
# 6 NA NA
数据:
df1 <- structure(list(x = c(2.33333333333333, 4.66666666666667, 5, 7.66666666666667,
NA, NA), y = c(6.33333333333333, 5.33333333333333, 3.33333333333333,
8.33333333333333, NA, NA)), row.names = c("1", "2", "3", "4",
"5", "6"), class = "data.frame")
使用 lag
、lead
和 mutate
来自 dplyr
df%>%
mutate(x=(lag(x,0)+lead(x)+lead(x,2))/3 , y=(lag(y,0)+lead(y)+lead(y,2))/3)