簡體   English   中英

R 根據 NA 之后的值以及有多少 NA 填充 NA

[英]R Fill NAs dependent on value after NAs and how many NAs there are

嗨,我想根據 NA 之后的第一個數字和有多少個 NA 在我的 data.frame 中填充 NA。 這是降雨數據,NA 顯示儀表未通信的時間,但我們知道該時期發生的總降雨量並希望對其進行平均。

這里有很多關於如何填充它們的問題,但我沒有發現任何需要使用 NA 數量的問題。 基本上我想通過丟失的時間步數來平均 NA 之后的數字值。

這是我的示例數據。 我已經使它變得非常簡單,但在實際示例中,我有數十萬個條目,並將按站點對數據進行分組。

library(tidyr)
library(dplyr)
library(zoo) 
testdf <- data.frame(DateTime = seq.POSIXt(
  from = as.POSIXct("2019-01-01"), to =  as.POSIXct("2019-01-02"), by = "hours"),
  Value = c(0,0,1,NA,NA,NA,-4,0,0,0,NA,NA,NA,NA,NA,-2,5,3,NA,-2,0,0,0,1,2))

使用tidyr::fillzoo:na.locf后,我可以輕松地用第一個值填充 NA:

tidyr::fill(testdf,Value, .direction = "up")

testdf %>% mutate(Filled = zoo::na.locf(Value, fromLast = T))

但我想將其除以連續出現的 NA 數加 1(即,如果有 5 個 NA 除以 6)。 理想情況下,我還想將 NA 之后的值更改為也等於這個新值,但如有必要,我可能會為此步驟修改一些內容。

如果有一種簡單的方法可以僅針對某些時期的差距(基本上是 na.locf 的 maxgap 功能)執行此操作,則獎勵積分就好像我有一兩個小時的平均時間差一樣,但如果是一周或一個月我想要將其保留為 NA。

示例輸出

desiredOutput <- data.frame(DateTime = seq.POSIXt(
  from = as.POSIXct("2019-01-01"), to =  as.POSIXct("2019-01-02"), by = "hours"),
  Value = c(0,0,1,-1,-1,-1,-1,0,0,0,-0.33,-0.33,-0.33,-0.33,-0.33,-0.33,5,3,-1,-1,0,0,0,1,2))

使用dplyr一種方法可能是創建組,使得連續NA之后的第一個非 NA 值包含在組中,這樣我們就可以只取last(Value)並將其除以組中的行數( n() )。 非 NA 的值存儲在它們各自的組中,只有一個元素,因此它們的計算不受影響,並且非 NA 數字返回相同的數字。

library(dplyr)

testdf %>%
   group_by(group = lag(cumsum(!is.na(Value)), default = 1)) %>%
   mutate(Value = last(Value)/n()) %>%
   ungroup %>%
   select(-group)

# A tibble: 25 x 2
#   DateTime            Value
#   <dttm>              <dbl>
# 1 2019-01-01 00:00:00     0
# 2 2019-01-01 01:00:00     0
# 3 2019-01-01 02:00:00     1
# 4 2019-01-01 03:00:00    -1
# 5 2019-01-01 04:00:00    -1
# 6 2019-01-01 05:00:00    -1
# 7 2019-01-01 06:00:00    -1
# 8 2019-01-01 07:00:00     0
# 9 2019-01-01 08:00:00     0
#10 2019-01-01 09:00:00     0
# … with 15 more rows

為了包含maxgap功能,我們可以用第一個Datetime減去最后一個Datetime ,如果它大於某個值,則將其replaceNA ,例如下面我已經完成了 10 小時的持續時間。

testdf %>%
   group_by(group = lag(cumsum(!is.na(Value)), default = 1)) %>%
   mutate(Value = last(Value)/n(), 
          Value = replace(Value, as.integer(difftime(DateTime[max(n() - 1, 1)],
                  first(DateTime), units = "hours")) > 10, NA))

我們可以使用data.table 按 'Value' 中非 NA 元素的邏輯向量的shift ed 累積總和分組,將last 'Value' 與行數相除並分配 ( := ) 以更新 'Value' 列

library(data.table)
setDT(testdf)[,  Value := last(Value)/.N, shift(cumsum(!is.na(Value)), fill = 1)]
testdf
#               DateTime      Value
# 1: 2019-01-01 00:00:00  0.0000000
# 2: 2019-01-01 01:00:00  0.0000000
# 3: 2019-01-01 02:00:00  1.0000000
# 4: 2019-01-01 03:00:00 -1.0000000
# 5: 2019-01-01 04:00:00 -1.0000000
# 6: 2019-01-01 05:00:00 -1.0000000
# 7: 2019-01-01 06:00:00 -1.0000000
# 8: 2019-01-01 07:00:00  0.0000000
# 9: 2019-01-01 08:00:00  0.0000000
#10: 2019-01-01 09:00:00  0.0000000
#11: 2019-01-01 10:00:00 -0.3333333
#12: 2019-01-01 11:00:00 -0.3333333
#13: 2019-01-01 12:00:00 -0.3333333
#14: 2019-01-01 13:00:00 -0.3333333
#15: 2019-01-01 14:00:00 -0.3333333
#16: 2019-01-01 15:00:00 -0.3333333
#17: 2019-01-01 16:00:00  5.0000000
#18: 2019-01-01 17:00:00  3.0000000
#9: 2019-01-01 18:00:00 -1.0000000
#20: 2019-01-01 19:00:00 -1.0000000
#21: 2019-01-01 20:00:00  0.0000000
#22: 2019-01-01 21:00:00  0.0000000
#23: 2019-01-01 22:00:00  0.0000000
#24: 2019-01-01 23:00:00  1.0000000
#25: 2019-01-02 00:00:00  2.0000000

可能很難在這里,這適應了相當具體的細節,但在一般的na_ma從均線歸集功能imputeTS包可以幫助您與平均周圍的缺失值的非NA值替換您的NAS。 它還具有所需的maxgap選項。

你可以打電話

library("imputeTS")
na_ma(x, k = 4, weighting = "simple", maxgap = 5)

這將用最接近的 4 個值(左邊 4 個,右邊 4 個)的平均值替換 NA 值。 使用 maxgap = 5 你定義,連續的 NA 運行,超過 5 的將離開 NA。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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