заполнить столбец предыдущим столбцом, если NA
у меня есть фрейм данных, как это
df <- data.frame(v1 = 10:14, v2 = c(NA, 1, NA, 3, 6), v3 = c(1, NA, NA, 9, 4))
v1 v2 v3
1 10 NA 1
2 11 1 NA
3 12 NA NA
4 13 3 9
5 14 6 4
Теперь я хочу заполнить NAs значением предыдущего столбца, поэтому он выглядит следующим образом:
v1 v2 v3
1 10 10 1
2 11 1 1
3 12 12 12
4 13 3 9
5 14 6 4
Я знаю, как это сделать вручную, например:
df$v2 <- ifelse(is.na(df$v2), df$v1, df$v2)
как я могу автоматизировать это для полного фрейма данных со многими столбцами?
5 ответов
вы можете сделать это с помощью fill
С tidyr
:
library(dplyr)
library(tidyr)
data.frame(t(df)) %>%
fill(., names(.)) %>%
t()
результат:
v1 v2 v3
X1 10 10 1
X2 11 1 1
X3 12 12 12
X4 13 3 9
X5 14 6 4
Примечание:
в основном, я транспонировал df
, заполнил каждую колонку вниз, затем переместил ее обратно в исходную ориентацию
for (i in 2:ncol(df))
df[,i] = ifelse(is.na(df[,i]), df[,i-1],df[,i])
это будет распространять значения по полосам столбцов NA. Если вы этого не хотите, просто измените порядок индексов в объявлении цикла for.
другой вариант с помощью Reduce
С ifelse
:
df[] <- Reduce(function(x, y) ifelse(is.na(y), x, y), df, accumulate = TRUE)
df
# v1 v2 v3
#1 10 10 1
#2 11 1 1
#3 12 12 12
#4 13 3 9
#5 14 6 4
можно использовать apply
но обратите внимание, что выход будет матрицей
t(apply(df, 1, function(x){
replace(x, is.na(x), x[cumsum(!is.na(x))][is.na(x)])
}))
# v1 v2 v3
#[1,] 10 10 1
#[2,] 11 1 1
#[3,] 12 12 12
#[4,] 13 3 9
#[5,] 14 6 4
С помощью zoo
na.locf
data.frame(t(apply(df,1,function(x) na.locf(x))))
v1 v2 v3
1 10 10 1
2 11 1 1
3 12 12 12
4 13 3 9
5 14 6 4