通过取 2x2 空间平均值将 data.frame 从 8x8 缩小到 4x4
Shrink data.frame from 8x8 to 4x4 by taking 2x2 spatial averages
假设我有以下数据框,其中每个观察值表示 2D 中特定点的给定变量 space:
data = data.frame(col1 = c(1,2,3,4,5,6,7,8), col2 = c(2,3,'NA',5,6,7,8,9), col3 = c(3,4,5,6,7,8,9,10), col4 = c(2,3,4,1,2,6,7,8),
col5 = c(2,3,'NA','NA',6,7,8,9), col6 = c(1,2,3,5,6,7,8,9), col7 = c(1,2,3,4,6,7,'NA','NA'), col8 = c(1,2,3,4,5,6,'NA','NA'))
> print(data)
col1 col2 col3 col4 col5 col6 col7 col8
1 1 2 3 2 2 1 1 1
2 2 3 4 3 3 2 2 2
3 3 NA 5 4 NA 3 3 3
4 4 5 6 1 NA 5 4 4
5 5 6 7 2 6 6 6 5
6 6 7 8 6 7 7 7 6
7 7 8 9 7 8 8 NA NA
8 8 9 10 8 9 9 NA NA
数据帧为 8x8(8 列和 8 行),因此总共有 36 个 obs。
我需要通过计算每个 2x2 观察组的平均值将其缩小到 4x4 数据框。
2x2 NA 组应该 return 一个 NA 值,而如果在 2x2 组中存在 < 4 个 NA,则平均值必须排除它们,例如2,2,2,NA = 2 的平均值。
这是我想要的输出:
newcol1 newcol2 newcol3 newcol4
2 3 2 1.50
4 4 4 3.50
6 5.75 6.50 6
8 8.50 8.50 NA
我想我可以用 for 循环解决这个问题,这是我尝试但没有成功的方法:
a = 1
b = 2
for (i in 1:15) {
test[[i]] = mean(c(data[a,a], data[a,b], data[b,a], data[b,b]))
test[[i]] = mean(c(data[a+i,a+i], data[a+i,b+i], data[b+i,a+i], data[b+i,b+i]))
}
我在网上搜索了很多,但没有找到任何类似的问题或解决方案。
有什么建议吗?
有没有可以做这种空间分析的R包?
这是一个愚蠢的解决方案(不是非常普遍),但适用于有限的示例。我想有一个更聪明的方法。
R8toR4 <- function(mat) {
stopifnot(identical(dim(mat), c(8L, 8L)))
out <- matrix(nrow = 4, ncol = 4)
for (i in 1:nrow(out)) {
for (j in 1:ncol(out)) {
submatrix <- mat[i * 2 - c(1, 0), j * 2 - c(1, 0)]
if (all(is.na(submatrix))) {
out[i, j] <- NA
} else {
out[i, j] <- mean(submatrix, na.rm = TRUE)
}
}
}
out
}
DataMatrix <- as.matrix(data)
R8toR4(DataMatrix)
[,1] [,2] [,3] [,4]
[1,] 2 3.00 2.0 1.5
[2,] 4 4.00 4.0 3.5
[3,] 6 5.75 6.5 6.0
[4,] 8 8.50 8.5 NA
来自链接 post,使用 @flodel answer,将 sum
替换为 mean
:
a <- as.matrix(data)
#convert matrix from char to num, ignore warnings, they are due to NAs
class(a) <- "numeric"
#adapted from @flodel
res <- tapply(a, list((row(a) + 1L) %/% 2L, (col(a) + 1L) %/% 2L), mean, na.rm = TRUE)
# remove NANs
res[ is.nan(res) ] <- NA
res
# 1 2 3 4
# 1 2 3.00 2.0 1.5
# 2 4 4.00 4.0 3.5
# 3 6 5.75 6.5 6.0
# 4 8 8.50 8.5 NA
假设我有以下数据框,其中每个观察值表示 2D 中特定点的给定变量 space:
data = data.frame(col1 = c(1,2,3,4,5,6,7,8), col2 = c(2,3,'NA',5,6,7,8,9), col3 = c(3,4,5,6,7,8,9,10), col4 = c(2,3,4,1,2,6,7,8),
col5 = c(2,3,'NA','NA',6,7,8,9), col6 = c(1,2,3,5,6,7,8,9), col7 = c(1,2,3,4,6,7,'NA','NA'), col8 = c(1,2,3,4,5,6,'NA','NA'))
> print(data)
col1 col2 col3 col4 col5 col6 col7 col8
1 1 2 3 2 2 1 1 1
2 2 3 4 3 3 2 2 2
3 3 NA 5 4 NA 3 3 3
4 4 5 6 1 NA 5 4 4
5 5 6 7 2 6 6 6 5
6 6 7 8 6 7 7 7 6
7 7 8 9 7 8 8 NA NA
8 8 9 10 8 9 9 NA NA
数据帧为 8x8(8 列和 8 行),因此总共有 36 个 obs。
我需要通过计算每个 2x2 观察组的平均值将其缩小到 4x4 数据框。
2x2 NA 组应该 return 一个 NA 值,而如果在 2x2 组中存在 < 4 个 NA,则平均值必须排除它们,例如2,2,2,NA = 2 的平均值。
这是我想要的输出:
newcol1 newcol2 newcol3 newcol4
2 3 2 1.50
4 4 4 3.50
6 5.75 6.50 6
8 8.50 8.50 NA
我想我可以用 for 循环解决这个问题,这是我尝试但没有成功的方法:
a = 1
b = 2
for (i in 1:15) {
test[[i]] = mean(c(data[a,a], data[a,b], data[b,a], data[b,b]))
test[[i]] = mean(c(data[a+i,a+i], data[a+i,b+i], data[b+i,a+i], data[b+i,b+i]))
}
我在网上搜索了很多,但没有找到任何类似的问题或解决方案。
有什么建议吗?
有没有可以做这种空间分析的R包?
这是一个愚蠢的解决方案(不是非常普遍),但适用于有限的示例。我想有一个更聪明的方法。
R8toR4 <- function(mat) {
stopifnot(identical(dim(mat), c(8L, 8L)))
out <- matrix(nrow = 4, ncol = 4)
for (i in 1:nrow(out)) {
for (j in 1:ncol(out)) {
submatrix <- mat[i * 2 - c(1, 0), j * 2 - c(1, 0)]
if (all(is.na(submatrix))) {
out[i, j] <- NA
} else {
out[i, j] <- mean(submatrix, na.rm = TRUE)
}
}
}
out
}
DataMatrix <- as.matrix(data)
R8toR4(DataMatrix)
[,1] [,2] [,3] [,4]
[1,] 2 3.00 2.0 1.5
[2,] 4 4.00 4.0 3.5
[3,] 6 5.75 6.5 6.0
[4,] 8 8.50 8.5 NA
来自链接 post,使用 @flodel answer,将 sum
替换为 mean
:
a <- as.matrix(data)
#convert matrix from char to num, ignore warnings, they are due to NAs
class(a) <- "numeric"
#adapted from @flodel
res <- tapply(a, list((row(a) + 1L) %/% 2L, (col(a) + 1L) %/% 2L), mean, na.rm = TRUE)
# remove NANs
res[ is.nan(res) ] <- NA
res
# 1 2 3 4
# 1 2 3.00 2.0 1.5
# 2 4 4.00 4.0 3.5
# 3 6 5.75 6.5 6.0
# 4 8 8.50 8.5 NA