我想在 1 之后使用 NA.fill,但在 -1 之后保留 NA。有沒有一個簡單的解決方案?
| 老的 | 新的 |
|---|---|
| 1 | 1 |
| 不適用 | 1 |
| 不適用 | 1 |
| 不適用 | 1 |
| -1 | -1 |
| 不適用 | 不適用 |
| 不適用 | 不適用 |
| 1 | 1 |
| 不適用 | 1 |
| 不適用 | 1 |
可重現的示例資料
dat <- read.table(text = "
Old New
1 1
NA 1
NA 1
NA 1
-1 -1
NA NA
NA NA
1 1
NA 1
NA 1", header = TRUE)
編輯:我在列中只有 1s 和 -1s。謝謝大家,答案很有幫助。我的“新”專欄現在正是我想要的。
uj5u.com熱心網友回復:
您可以使用回圈
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
uj5u.com熱心網友回復:
這是一種使用rle, give or take a 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,然后轉換回NAis.na(r$values[-1]) & r$values[-length(r$values)] == 1確定一個值是否NA和前一個值是1;- 我們使用該值 (as
ind) 來確定要替換哪些值 (c(F, ind)) 以及將哪些值替換為 (c(ind, F)); inverse.rle做它應該做的:重新生成向量,但現在將 1-following-NA值更改為1,沒有其他更改
如果邏輯改為“除非先前的值不是 -1,否則填充 NA”(如果還有非1值應該填充),則將ind計算從更改== 1為!= -1。
uj5u.com熱心網友回復:
使用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
uj5u.com熱心網友回復:
類似于@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
uj5u.com熱心網友回復:
與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
uj5u.com熱心網友回復:
與cumsum:
df$Old[as.logical(cumsum(replace(df$Old, is.na(df$Old), 0)))] <- 1
uj5u.com熱心網友回復:
您可以通過這樣做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
我認為這個問題也可能有幫助。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/338789.html
