有一个数据帧为blow(具有NA值(
md <- data.frame(cat=c('a','b','d',NA,'E',NA),
subcat=c('A','C',NA,NA,NA,'D'))
cat subcat
1 a A
2 b C
3 d <NA>
4 <NA> <NA>
5 E <NA>
6 <NA> D
我想用前面的字符替换NA,结果如下。
正在使用类似"for…"的循环语句可以做到,但效率不高。有什么配方或包装可以做到这一点吗?谢谢
cat subcat
1 a A
2 b C
3 d C
4 d C
5 E C
6 E D
您可以使用zoo
包中的na.locf
函数。
zoo::na.locf(md)
cat subcat
1 a A
2 b C
3 d C
4 d C
5 E C
6 E D
或者分别使用tidyr
和dplyr
中的fill
和everything
。
library(dplyr)
library(tidyr)
md %>% fill(everything())
# cat subcat
# 1 a A
# 2 b C
# 3 d C
# 4 d C
# 5 E C
# 6 E D
一种方法是使用行程长度编码rle()
。因为它不编码NA,所以我用字符串"替换了它们;NA";。
roll_na <- function(.) {
.[is.na(.)] <- "NA"
var <- rle(.)
na_ind <- which(var$values == "NA")
var_lag <- c(NA, var$values[-length(var$values)])
var$values[na_ind] <- var_lag[na_ind]
rep(var$values, times = var$lengths)
}
library(dplyr)
md %>%
mutate(across(everything(), roll_na))
# cat subcat
# 1 a A
# 2 b C
# 3 d C
# 4 d C
# 5 E C
# 6 E D
如果在大列向量中有很多连续的NA
,这不是一种方法,但如果只有几个,它会很快:
no_NA <- function(x) {while(any(is.na(x))) x[is.na(x)] <- x[which(is.na(x))-1]; x}
as.data.frame(apply(md, 2, no_NA))
如果你有一个有很多NA
s的大数据集,我会使用一个简单的while
循环,它会从每个向量的开始改变所有的NA
s
no_NA <- function(x){
len <- length(x); i <- 2
while(i <= len){
if (is.na(x[i])) x[i] <- x[i-1]
i <- i + 1
}
x
}
as.data.frame(apply(md, 2, no_NA))
忽略NA
是列的初始值的情况,可以使用以下函数
# Replacement function
func = function(DF){
tmp = DF
for(i in 1:length(tmp[1,])){
for(j in 1:length(tmp[,i])){
if(j == 1){
next
} else if (is.na(tmp[j,i])) {
tmp[j,i] = tmp[j-1,i]
}
}
}
return(tmp)
}
做
# data
md = func(md)
print(md)
输出
cat subcat
1 a A
2 b C
3 d C
4 d C
5 E C
6 E D
library(tidyverse)
library(magrittr)
#>
#> Attaching package: 'magrittr'
#> The following object is masked from 'package:purrr':
#>
#> set_names
#> The following object is masked from 'package:tidyr':
#>
#> extract
md <- data.frame(cat=c(NA,'b','d',NA,'E',NA),
subcat=c(NA,'C',NA,NA,NA,'D'))
md
#> cat subcat
#> 1 <NA> <NA>
#> 2 b C
#> 3 d <NA>
#> 4 <NA> <NA>
#> 5 E <NA>
#> 6 <NA> D
#if the first value is NA
value <- '0'
md <-
map(md, ~{
if(is.na(.x[[1]])) {
c(value, .x[-1])
} else {
.x
}
}) %>% bind_cols()
#while loop is needed for consecutive NA's
while (any(map_lgl(md, ~any(is.na(..1))))) {
md %<>% mutate(cat = if_else(is.na(cat), lag(cat), cat),
subcat = if_else(is.na(subcat), lag(subcat), subcat))
}
md
#> # A tibble: 6 x 2
#> cat subcat
#> <chr> <chr>
#> 1 0 0
#> 2 b C
#> 3 d C
#> 4 d C
#> 5 E C
#> 6 E D
创建于2021-06-11由reprex包(v2.0.0(