[英]How can I find periodically appearing NA values in an 3D array (along dimension time) with R
我有一個數組中的空間數據(最初為ncdf)的時間序列(月數值超過幾年)。 如果有超過2個連續的例如帶有NA的januaries,我想通過在所有時間步驟中將其置於NA來完全禁止進一步研究這個像素(現在是一個時間步長矩陣中的單元格)。
就我而言,“time.series”僅對矢量或矩陣有效(最多為二維)。
我可以看到(但也沒有設法實現)的一個解決方法是:按照順序不再按照時間順序排列數組,而是按月排序(jan 2001,jan2002,jan 2003,feb 2001,feb 2002,feb 2003年,...)已經有很多幫助了。 但是如果例如像素那么像素會得到NA。 2002年1月,2003年1月和2001年2月是NA。
任何幫助將非常感激。 請問我的問題是否不清楚 - 這是我的第一個 - 我盡我所能。
編輯:我的實際數據集是基於全球衛星的輻射數據集。 由於例如周期性出現的雲(在每年同一個月的雨季期間),不應再考慮這些像素。 我還有其他一些消除像素的標准。 只缺少一個標准。
# create any array with scattered NAs
set.seed (10)
array <- replicate(48, replicate(10, rnorm(20)))
na_pixels <- array((sample(c(1, NA), size = 7200, replace = TRUE, prob = c(0.95, 0.05))), dim = c(20,10,48))
na_array <- array * na_pixels
dimnames(na_array) <- list(NULL, NULL, as.character(seq(as.Date("2001-01-01"), as.Date("2004-12-01"), "month")))
#I want to test several conditions that would make a pixel not usable for me
#in the end I want to retrieve a mask of usable "pixels".
#what I am doing already is:
mask <- apply(na_array, MARGIN = c(1,2), FUN=function(x){
#check if more than 10% of a pixel are NA over time
if (sum(is.na(x)) > (length(x)*0.05)){
mask_val <- 0
}
#check if more than 5 pixel are missing consecutively
else if (max(with(rle(is.na(a)), lengths[values])) > 5){
mask_val <- 0
}
#this is the missing part
else if (...more than 2 januaries or 2 feburaries or... are NA){#check for periodically appearing NAs
mask_val <- 0
}
else {
mask_val <- 1
}
return(mask_val)
})
可能更方便(如果存在必要的內存)在“長”“data.frame”中更改3D數組:
as.data.frame(as.table(na_array))
# Var1 Var2 Var3 Freq
#1 A A 2001-01-01 0.01874617
#2 B A 2001-01-01 -0.18425254
#3 C A 2001-01-01 -1.37133055
# ...........................
#9598 R J 2004-12-01 NA
#9599 S J 2004-12-01 -1.11411416
#9600 T J 2004-12-01 0.01435433
它不是依賴於as.table
和as.data.frame
強制,而是可以手動完成並且更有效:
dat = data.frame(i = rep_len(seq_len(dim(na_array)[1]), prod(dim(na_array))),
j = rep_len(rep(seq_len(dim(na_array)[2]), each = dim(na_array)[1]), prod(dim(na_array))),
date = rep(as.Date(dimnames(na_array)[[3]]), each = prod(dim(na_array)[1:2])) ,
month = rep(format(as.Date(dimnames(na_array)[[3]]), "%b"), each = prod(dim(na_array)[1:2])),
isNA = c(is.na(na_array)))
dat
# i j date month isNA
#1 1 1 2001-01-01 Jan FALSE
#2 2 1 2001-01-01 Jan FALSE
#3 3 1 2001-01-01 Jan FALSE
#4 4 1 2001-01-01 Jan TRUE
# ..............
#9597 17 10 2004-12-01 Dec FALSE
#9598 18 10 2004-12-01 Dec TRUE
#9599 19 10 2004-12-01 Dec FALSE
#9600 20 10 2004-12-01 Dec FALSE
凡i
:行na_array
, j
:列na_array
, date
:第3暗淡na_array
, month
:在月date
柱(因為它會在以后需要的話), isNA
:的值是否na_array
是NA
。
並建立三個條件:
cond1 = aggregate(isNA ~ i + j, dat, function(x) sum(x) > (dim(na_array)[3] * 0.05))
(創建cond1
更有效方法是rowSums(is.na(na_array), dims = 2) > (dim(na_array)[3] * 0.05)
)。
cond2 = aggregate(isNA ~ i + j, dat, function(x) any(with(rle(x), lengths[values]) > 5))
並且為了計算cond3
,首先找到每個“單元”每個“月”的缺失值的數量(即[i,j])(“月”是從dimnames(na_array)[[3]]
創建/提取的dimnames(na_array)[[3]]
在開頭創建'long'“data.frame” dat
時:
NA_per_month = aggregate(isNA ~ i + j + month, dat, function(x) sum(x))
對於每個[i,j],每個“月”具有NA
s的數量,我們通過檢查每個[i,j]是否包含具有超過2個NA
的any
“月”來構建cond3
:
cond3 = aggregate(isNA ~ i + j, NA_per_month, function(x) any(x > 2))
(在上述“分組”操作中用任何其他可用的替換aggregate
是微不足道的) 。
也許我們可以避免創建一個“長”“data.frame”並直接在na_array
上na_array
。 例如,使用rowSums
版本計算cond1
更加高效和簡單。 cond2
也可以通過對na_array
的apply
來保存。 但cond3
使用“長”“data.frame”變得更加直接,而不是使用3D數組。 因此,考慮到效率,嘗試使用數據中存在的結構總是更好,如果它變得足夠麻煩,那么我們應該改變一次數據的結構並計算另一個腳手架中的任何東西。
要獲得最終結果,請分配適當大小的“矩陣”:
ans = matrix(NA, dim(na_array)[1], dim(na_array)[2])
在OR
條件之后填寫:
ans[cbind(cond1$i, cond1$j)] = cond1$isNA | cond2$isNA | cond3$isNA
ans
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] TRUE TRUE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE
# [2,] TRUE FALSE FALSE FALSE TRUE TRUE FALSE TRUE FALSE FALSE
# [3,] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
# [4,] FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE
# [5,] FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE
# [6,] FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
# [7,] FALSE FALSE TRUE TRUE TRUE FALSE FALSE TRUE TRUE FALSE
# [8,] TRUE TRUE TRUE TRUE FALSE FALSE TRUE FALSE TRUE FALSE
# [9,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
#[10,] TRUE FALSE TRUE TRUE FALSE FALSE FALSE TRUE FALSE FALSE
#[11,] FALSE TRUE TRUE FALSE FALSE TRUE FALSE TRUE FALSE FALSE
#[12,] TRUE TRUE TRUE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
#[13,] FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE
#[14,] FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE
#[15,] TRUE TRUE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE
#[16,] FALSE FALSE FALSE TRUE TRUE FALSE TRUE TRUE TRUE TRUE
#[17,] TRUE FALSE TRUE TRUE FALSE FALSE TRUE FALSE TRUE FALSE
#[18,] FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE
#[19,] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE
#[20,] TRUE FALSE TRUE TRUE FALSE TRUE TRUE FALSE FALSE TRUE
@ alexis_laz:是的,現在有效。 不幸的是我意識到ans[cbind(cond1$i, cond1$j)] = cond1$isNA | cond2$isNA | cond3$isNA
ans[cbind(cond1$i, cond1$j)] = cond1$isNA | cond2$isNA | cond3$isNA
ans[cbind(cond1$i, cond1$j)] = cond1$isNA | cond2$isNA | cond3$isNA
不起作用。 我收到錯誤:要替換的項目數不是替換長度的倍數。 我認為只需要cond1進行更換。 (我很抱歉我的示例數據集在cond2和cond3的所有情況下都給出'FALSE'但是,它應該檢查代碼中的'OR'。即使結果看起來像cond1一樣)我想出了下面的代碼,它可以工作,但絕對不是很好或有效,因為我不太熟悉布爾的東西。 也許你可以優化我的代碼或編輯你的行(因為我的真實數據集是巨大的,我會很高興fpr任何優化)。 在遠端,我需要所有True條件(意味着NA)為0,所有FALSE條件為1.這就是為什么我已經在我的代碼中這樣做了。
ans = matrix(NA, dim(na_array)[1], dim(na_array)[2])
cond1_bool <- ans
cond1_bool[cbind(cond1$i, cond1$j)] = cond1$isNA
cond2_bool <- ans
cond2_bool[cbind(cond2$i, cond2$j)] = cond2$isNA
cond3_bool <- ans
cond3_bool[cbind(cond3$i, cond3$j)] = cond3$isNA
ans_bool <- ans
ans_bool[which(cond1_bool == T|cond2_bool == T|cond3_bool == T)] <- 0
ans_bool[which(is.na(ans_bool))] <- 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.