问题
Say I have the following data.frame:
t<-c(1,1,2,4,5,4)
u<-c(1,3,4,5,4,2)
v<-c(2,3,4,5,NA,2)
w<-c(NA,3,4,5,2,3)
x<-c(2,3,4,5,6,NA)
df<-data.frame(t,u,v,w,x)
I would like to replace the NAs with values that represent the average of the case before and after the NA, unless a row starts (row 4) or ends (row 5) with an NA. When the row begins with NA, I would like to substitute the NA with the following case. When the row ends with NA, I would like to substitute the NA with the previous case.
Thus, I would like my output to look like:
t<-c(1,1,2,4,5,4)
u<-c(1,3,4,5,4,2)
v<-c(2,3,4,5,3.5,2)
w<-c(3,3,4,5,2,3)
x<-c(2,3,4,5,6,6)
df<-data.frame(t,u,v,w,x)
回答1:
The question refers to row 4 starting with NA and row 5 ending in NA but in fact column 4 of the input df
starts with an NA and column 5 of the input ends with an NA and neither row 4 nor row 5 of the input start or end with an NA so we will assume that column was meant, not row. Also there are two data frames both named df
in the question. Evidently one is supposed to represent the input and the other data frame having the same name is the output but for complete clarity we have repeated the definition of the df
we have used in the Note at the end.
na.approx
in zoo pretty much does this. (If a matrix result is OK then omit the data.frame()
part.)
library(zoo)
data.frame(na.approx(df, rule = 2))
giving:
t u v w x
1 1 1 2.0 3 2
2 1 3 3.0 3 3
3 2 4 4.0 4 4
4 4 5 5.0 5 5
5 5 4 3.5 2 6
6 4 2 2.0 3 6
Note: For clarity, we used this data frame as input above:
df <- structure(list(t = c(1, 1, 2, 4, 5, 4), u = c(1, 3, 4, 5, 4,
2), v = c(2, 3, 4, 5, NA, 2), w = c(NA, 3, 4, 5, 2, 3), x = c(2,
3, 4, 5, 6, NA)), .Names = c("t", "u", "v", "w", "x"), row.names = c(NA,
-6L), class = "data.frame")
回答2:
sapply(df, function(x){
replace(x, is.na(x), rowMeans(cbind(c(NA, head(x, -1)), c(x[-1], NA)), na.rm = TRUE)[is.na(x)])
})
# t u v w x
#[1,] 1 1 2.0 3 2
#[2,] 1 3 3.0 3 3
#[3,] 2 4 4.0 4 4
#[4,] 4 5 5.0 5 5
#[5,] 5 4 3.5 2 6
#[6,] 4 2 2.0 3 6
来源:https://stackoverflow.com/questions/46712895/replace-na-with-average-of-the-case-before-and-after-the-na