上下文:我正在处理组织为具有以下结构的4D阵列的调查数据:m[n_sites, n_surveys, n_years, n_species]
。
问题:不过有一些数据是随机丢失的,我想把丢失的数据移到每行的末尾。
示例:以下是原始数据:
, , 1, 1
1 2 3 4 5
1 NA 2 NA 2 3
2 NA 3 1 NA NA
3 4 NA NA 4 6
4 2 NA NA 2 1
我想把它重新排列成:
, , 1, 1
1 2 3 4 5
1 2 2 3 NA NA
2 3 1 NA NA NA
3 4 4 6 NA NA
4 2 2 1 NA NA
注意:不过数据非常大,所以我需要一些高效且相当简单的东西。
可复制代码:
library(magrittr) ## for %>% pipe
library(reshape2) ## for acast
set.seed(1)
# Simulate survey data
df <- expand.grid(
species = c(1,2),
year = c(1,2,3),
site = c(1,2,3,4),
survey = c(1,2,3,4,5))
df$counts <- rpois(n = nrow(df), lambda = 3)
# Add random NAs (missing data)
posNA <- sample(x = 1:nrow(df), size = 0.5 * nrow(df), replace = FALSE)
df$counts[posNA] <- NA
# Cast to 4d array
m <- df %>% acast(site ~ survey ~ year ~ species)
您可以在行和第3维度和第4维度上使用na.omit
,按列数更正length
,并使用aperm
转置结果。
## 4D-array
apply(m, c(1, 3, 4), (x) `length<-`(na.omit(x), dim(m)[2])) |> aperm(c(2, 1, 3, 4))
# , , 1, 1
#
# [,1] [,2] [,3] [,4] [,5]
# 1 2 2 3 NA NA
# 2 3 1 NA NA NA
# 3 4 4 6 NA NA
# 4 2 2 1 NA NA
#
# , , 2, 1
#
# [,1] [,2] [,3] [,4] [,5]
# 1 3 0 3 NA NA
# 2 3 3 2 3 NA
# 3 3 4 NA NA NA
# 4 6 3 1 NA NA
#
# , , 3, 1
#
# [,1] [,2] [,3] [,4] [,5]
# 1 2 NA NA NA NA
# 2 2 1 NA NA NA
# 3 4 2 NA NA NA
# 4 4 0 4 3 NA
#
# , , 1, 2
#
# [,1] [,2] [,3] [,4] [,5]
# 1 2 2 NA NA NA
# 2 4 3 8 NA NA
# 3 2 1 2 3 NA
# 4 4 NA NA NA NA
#
# , , 2, 2
#
# [,1] [,2] [,3] [,4] [,5]
# 1 5 5 NA NA NA
# 2 4 NA NA NA NA
# 3 2 1 NA NA NA
# 4 5 NA NA NA NA
#
# , , 3, 2
#
# [,1] [,2] [,3] [,4] [,5]
# 1 5 2 2 2 NA
# 2 1 4 2 3 NA
# 3 8 2 3 NA NA
# 4 5 NA NA NA NA
另外,在一个更简单的数组中演示逻辑:
## 3D-array
a
# , , 1
#
# [,1] [,2] [,3] [,4]
# [1,] NA NA 1 3
# [2,] 4 1 1 NA
# [3,] NA 3 NA 4
#
# , , 2
#
# [,1] [,2] [,3] [,4]
# [1,] 3 2 2 4
# [2,] 1 NA 3 4
# [3,] 1 NA 4 3
apply(a, c(1, 3), (x) `length<-`(na.omit(x), dim(a)[2])) |> aperm(c(2, 1, 3))
# , , 1
#
# [,1] [,2] [,3] [,4]
# [1,] 1 3 NA NA
# [2,] 4 1 1 NA
# [3,] 3 4 NA NA
#
# , , 2
#
# [,1] [,2] [,3] [,4]
# [1,] 3 2 2 4
# [2,] 1 3 4 NA
# [3,] 1 4 3 NA
数据:
m <- structure(c(NA, NA, 4L, 2L, 2L, 3L, NA, NA, NA, 1L, NA, NA, 2L,
NA, 4L, 2L, 3L, NA, 6L, 1L, 3L, 3L, NA, 6L, 0L, 3L, NA, 3L, NA,
2L, 3L, 1L, 3L, 3L, 4L, NA, NA, NA, NA, NA, 2L, 2L, 4L, 4L, NA,
NA, NA, 0L, NA, NA, NA, NA, NA, NA, NA, 4L, NA, 1L, 2L, 3L, NA,
4L, 2L, NA, NA, 3L, 1L, NA, NA, NA, 2L, 4L, 2L, NA, NA, NA, 2L,
8L, 3L, NA, 5L, NA, NA, NA, NA, NA, NA, NA, 5L, NA, 2L, NA, NA,
4L, 1L, 5L, NA, NA, NA, NA, 5L, 1L, 8L, NA, 2L, 4L, NA, NA, 2L,
NA, 2L, 5L, NA, 2L, NA, NA, 2L, 3L, 3L, NA), dim = c(4L, 5L,
3L, 2L), dimnames = list(c("1", "2", "3", "4"), c("1", "2", "3",
"4", "5"), c("1", "2", "3"), c("1", "2")))
a <- structure(c(NA, 4L, NA, NA, 1L, 3L, 1L, 1L, NA, 3L, NA, 4L, 3L,
1L, 1L, 2L, NA, NA, 2L, 3L, 4L, 4L, 4L, 3L), dim = c(3L, 4L,
2L))
我们可以使用
m1 <- m
for(i in seq_len(dim(m)[3]))
for(j in seq_len(dim(m)[4]))
m1[,, i, j] <- t(apply(m1[,, i, j], 1,
function(x) x[order(is.na(x))]))
-输出
> m1[,, 1, 1]
1 2 3 4 5
1 2 2 3 NA NA
2 3 1 NA NA NA
3 4 4 6 NA NA
4 2 2 1 NA NA