在值之间的数据框中填写 NA

fill in NAs in dataframe between values

我有一个示例数据集

newdata<-data.frame(Tow.y=c(21,"NA","NA","NA","NA","NA",22,"NA","NA","NA","NA","NA",23,"NA","NA"),Tow=c("NA","NA","NA",21,"NA","NA","NA","NA",22,"NA","NA","NA","NA","NA",23))
newdata$Tow.y<-as.numeric(as.character(newdata$Tow.y))
newdata$Tow<-as.numeric(as.character(newdata$Tow))

newdata1<-newdata %>% 
  mutate(Station = coalesce(Tow.y, Tow))
newdata1

生成的代码产生:

Tow.y Tow Station
1     21  NA      21
2     NA  NA      NA
3     NA  NA      NA
4     NA  21      21
5     NA  NA      NA
6     NA  NA      NA
7     22  NA      22
8     NA  NA      NA
9     NA  22      22
10    NA  NA      NA
11    NA  NA      NA
12    NA  NA      NA
13    23  NA      23
14    NA  NA      NA
15    NA  23      23

我想为 Station 中唯一值之间的 NA 填写 NA。因此,两个 21 值之间的 NA 将是 21,22 之间的 NA 将是 22,等等。连续数字之间的 NA 将保持 NA。

像这样:

  Tow.y Tow Station
1     21  NA      21
2     NA  NA      21
3     NA  NA      21
4     NA  21      21
5     NA  NA      NA
6     NA  NA      NA
7     22  NA      22
8     NA  NA      22
9     NA  22      22
10    NA  NA      NA
11    NA  NA      NA
12    NA  NA      NA
13    23  NA      23
14    NA  NA      23
15    NA  23      23

我尝试了 zoo 包中的 na.locf 函数,但它替换了所有 NA 值。

newdata1$Station2<-na.locf(newdata1$Station,na.rm = F)

我看过的其他示例显示您可以将 na.locf 与组变量一起使用,但我没有针对数据集的完整分组变量。有没有人有办法在我需要填写的地方填写 NA。

这是一个好方法。我留下了辅助列来演示它是如何工作的,但你可以使用 select.

轻松删除它们
newdata1 %>%
  mutate(from_first = zoo::na.locf(Station, na.rm = FALSE),
         from_last = zoo::na.locf(Station, na.rm = FALSE, fromLast = TRUE),
         result = if_else(from_first == from_last, from_first, Station))
#    Tow.y Tow Station from_first from_last result
# 1     21  NA      21         21        21     21
# 2     NA  NA      NA         21        21     21
# 3     NA  NA      NA         21        21     21
# 4     NA  21      21         21        21     21
# 5     NA  NA      NA         21        22     NA
# 6     NA  NA      NA         21        22     NA
# 7     22  NA      22         22        22     22
# 8     NA  NA      NA         22        22     22
# 9     NA  22      22         22        22     22
# 10    NA  NA      NA         22        23     NA
# 11    NA  NA      NA         22        23     NA
# 12    NA  NA      NA         22        23     NA
# 13    23  NA      23         23        23     23
# 14    NA  NA      NA         23        23     23
# 15    NA  23      23         23        23     23

根据示例,'Tow' 和 'Tow.y' 值似乎以 'start'、'end' 方式匹配。在这种情况下,我们可以使用 base R 方法。

创建序列索引 ('i1') 以复制 'Tow'(或 'Tow.y')中的非 NA 元素用于 'Station' 列。 'lst'returns一个list的数值索引,用于给'Station'

赋值
lst <- do.call(Map, c(f = seq, unname(lapply(newdata,
          function(x) seq_along(x)[!is.na(x)]))))
i1 <- unlist(lst)    
newdata$Station[i1] <- rep(na.omit(newdata$Tow), lengths(lst))
newdata
#   Tow.y Tow Station
#1     21  NA      21
#2     NA  NA      21
#3     NA  NA      21
#4     NA  21      21
#5     NA  NA      NA
#6     NA  NA      NA
#7     22  NA      22
#8     NA  NA      22
#9     NA  22      22
#10    NA  NA      NA
#11    NA  NA      NA
#12    NA  NA      NA
#13    23  NA      23
#14    NA  NA      23
#15    NA  23      23

或者使用与tidyverse

相同的逻辑
library(tidyverse)
newdata %>% 
    mutate_all(funs(row_number() * !is.na(.))) %>% 
    map( ~ .x[.x!=0]) %>% 
               transpose %>%
               map(reduce, `:`) %>% 
    set_names(na.omit(newdata$Tow)) %>%
    stack %>%
    right_join(newdata %>% mutate(values = row_number())) %>% 
    rename(Station = ind) %>%
    ungroup %>%

    select(names(newdata), everything(), -values)
#   Tow.y Tow Station
#1     21  NA      21
#2     NA  NA      21
#3     NA  NA      21
#4     NA  21      21
#5     NA  NA    <NA>
#6     NA  NA    <NA>
#7     22  NA      22
#8     NA  NA      22
#9     NA  22      22
#10    NA  NA    <NA>
#11    NA  NA    <NA>
#12    NA  NA    <NA>
#13    23  NA      23
#14    NA  NA      23
#15    NA  23      23