我想用NA。在1之后填充,但在-1之后保留NA。有没有简单的解决办法?
<表类>
老
新
tbody><<tr>1 1 NA 1 NA 1 NA 1 11 NA NA NA NA 11 NA 1 NA 1 表类>
你可以使用一个循环
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
您可以通过fill
和ifelse
来实现
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
我想这个问题也可能有帮助。