Mam to dane.frame pełne NA.
DATE <- c("1","2","3","4","5","6","7","1","2","3","4","5","6","7")
COMP <- c("A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B")
BM <- c(12,11,NA,14,NA,15,NA, 5, 5, NA, 6, NA, 8, 9)
df <- data.frame(DATE, COMP, BM, stringsAsFactors=F)
df
# DATE COMP BM
# 1 1 A 12
# 2 2 A 11
# 3 3 A NA
# 4 4 A 14
# 5 5 A NA
# 6 6 A 15
# 7 7 A NA
# 8 1 B 5
# 9 2 B 5
# 10 3 B NA
# 11 4 B 6
# 12 5 B NA
# 13 6 B 8
# 14 7 B 9
Chcę zastąpić te NA środkami średnimiwartości w poprzednim i następnym wierszu (tylko jeśli jest to ta sama firma oczywiście) .Jeśli pierwszym wierszem jest NA, należy przyjąć następującą wartość wiersza, jeśli ostatni wiersz jest NA, drugi ostatni wiersz wartość powinna zostać pobrana.
Wynik powinien wyglądać tak
# DATE COMP BM
# 1 1 A 12
# 2 2 A 11
# 3 3 A 12.5
# 4 4 A 14
# 5 5 A 14.5
# 6 6 A 15
# 7 7 A 15
# 8 1 B 5
# 9 2 B 5
# 10 3 B 5.5
# 11 4 B 6
# 12 5 B 7
# 13 6 B 8
# 14 7 B 9
Dziękuję Ci!
Odpowiedzi:
3 dla odpowiedzi № 1To jest praca dla zoo:::na.approx
:
library(plyr)
library(zoo)
ddply(df, .(COMP), transform, BM=na.approx(BM, rule=2))
# DATE COMP BM
# 1 1 A 12.0
# 2 2 A 11.0
# 3 3 A 12.5
# 4 4 A 14.0
# 5 5 A 14.5
# 6 6 A 15.0
# 7 7 A 15.0
# 8 1 B 5.0
# 9 2 B 5.0
# 10 3 B 5.5
# 11 4 B 6.0
# 12 5 B 7.0
# 13 6 B 8.0
# 14 7 B 9.0
Edytować:
W odpowiedzi na komentarz: Musisz obsługiwać sprawy z tylko jedną wartością inną niż NA lub z tylko wartości NA.
my.na.approx <- function(x) {
if (sum(is.finite(x)) == 0L) return(x)
if (sum(is.finite(x)) == 1L) return(na.approx(x, rule=2, method="constant"))
na.approx(x, rule=2)
}
my.na.approx(c(NA, 1, NA, NA, 2, NA))
#[1] 1.000000 1.000000 1.333333 1.666667 2.000000 2.000000
my.na.approx(c(NA, NA, NA, NA, 2, NA))
#[1] 2 2 2 2 2 2
my.na.approx(c(NA, NA, NA, NA, NA, NA))
#[1] NA NA NA NA NA NA