簡體   English   中英

如何在R中找到3D陣列中的周期性出現的NA值(沿維度時間)

[英]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.tableas.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_arrayj :列na_arraydate :第3暗淡na_arraymonth :在月date柱(因為它會在以后需要的話), isNA :的值是否na_arrayNA

並建立三個條件:

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個NAany “月”來構建cond3

cond3 = aggregate(isNA ~ i + j, NA_per_month, function(x) any(x > 2))

(在上述“分組”操作中用任何其他可用的替換aggregate是微不足道的)

也許我們可以避免創建一個“長”“data.frame”並直接在na_arrayna_array 例如,使用rowSums版本計算cond1更加高效和簡單。 cond2也可以通過對na_arrayapply來保存。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM