r语言 - Na填充在特定值之后



我想用NA。在1之后填充,但在-1之后保留NA。有没有简单的解决办法?

<表类> 老 新 tbody><<tr>11NA1NA1NA111NANANANA11NA1NA1

你可以使用一个循环

x = c(1,NA,NA,NA,-1,NA,NA,1,NA,NA)
for (i in seq_along(x)[-1]) {
if (!is.na(x[i-1]) & x[i-1] == 1 & is.na(x[i])) x[i] = 1
}
# [1]  1  1  1  1 -1 NA NA  1  1  1

这是一种使用rle的方法,给予或采取hack

r <- rle(ifelse(is.na(dat$Old), -Inf, dat$Old))
r$values[is.infinite(r$values)] <- NA_integer_
r
# Run Length Encoding
#   lengths: int [1:6] 1 3 1 2 1 2
#   values : num [1:6] 1 NA -1 NA 1 NA
ind <- is.na(r$values[-1]) & r$values[-length(r$values)] == 1
ind
# [1]  TRUE FALSE FALSE FALSE  TRUE
r$values[c(FALSE, ind)] <- r$values[c(ind, FALSE)]
inverse.rle(r)
#  [1]  1  1  1  1 -1 NA NA  1  1  1

指出:

  • rle将所有缺失值(即NA)视为不相等的,这违背了我们预期使用的游程长度编码;我通过首先将NA转换为-Inf来解决这个问题(有些武断,我认为极不可能出现在实际数据中),运行rle,然后转换回NA
  • is.na(r$values[-1]) & r$values[-length(r$values)] == 1判断其中一个值为NA,前一个值为1;
  • 我们使用这个值(作为ind)来决定哪些值要替换(c(F, ind)),哪些值要替换(c(ind, F));
  • inverse.rle做它应该做的:重新生成矢量,但现在与1-following-NA值更改为1,没有其他更改

如果逻辑是"填充NA,除非前一个值不是-1">(如果也有非1值应该填充)通过将ind计算从== 1更改为!= -1

Withcumsum:

df$Old[as.logical(cumsum(replace(df$Old, is.na(df$Old), 0)))] <- 1

使用data.table:

library(data.table)
setDT(dat)[, x := fifelse(is.na(Old) & head(Old, 1) == 1, head(Old, 1), Old), 
by = cumsum(!is.na(Old)) ]
df
#     Old New  x
#  1:   1   1  1
#  2:  NA   1  1
#  3:  NA   1  1
#  4:  NA   1  1
#  5:  -1  -1 -1
#  6:  NA  NA NA
#  7:  NA  NA NA
#  8:   1   1  1
#  9:  NA   1  1
# 10:  NA   1  1

类似于@Otto Kässi的逻辑使用zoo::na.locf-

transform(dat, New = zoo::na.locf(Old)) |>
transform(New = ifelse(New == -1, Old, New))
#   Old New
#1    1   1
#2   NA   1
#3   NA   1
#4   NA   1
#5   -1  -1
#6   NA  NA
#7   NA  NA
#8    1   1
#9   NA   1
#10  NA   1

purrr::reduce:

library(tidyverse)
reduce(2:nrow(dat), function(x,y) {
if (is.na(x$Old[y]) & !is.na(x$Old[y-1]) & x$Old[y-1] == 1) x$Old[y] <- 1; x},
.init=dat)
#>    Old New
#> 1    1   1
#> 2    1   1
#> 3    1   1
#> 4    1   1
#> 5   -1  -1
#> 6   NA  NA
#> 7   NA  NA
#> 8    1   1
#> 9    1   1
#> 10   1   1

您可以通过fillifelse来实现

library(tidyverse)
dat <- structure(list(Old = c(1L, NA, NA, NA, -1L, NA, NA, 1L, NA, NA
)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"
)) 
dat %>% 
mutate(New = Old) %>% 
fill(New) %>% 
mutate(New = ifelse(New == -1, Old, New)) %>% 
select(Old, New)

结果:

# A tibble: 10 x 2
Old   New
<int> <int>
1     1     1
2    NA     1
3    NA     1
4    NA     1
5    -1    -1
6    NA    NA
7    NA    NA
8     1     1
9    NA     1
10    NA     1

我想这个问题也可能有帮助。

最新更新