Последнее наблюдение в кадре данных? [дубликат]
этот вопрос уже есть ответ здесь:
Я хочу реализовать "последнее наблюдение" для набора данных, над которым я работаю, в конце которого отсутствуют значения.
вот простой код, чтобы сделать это (вопрос после это):
LOCF <- function(x)
{
    # Last Observation Carried Forward (for a left to right series)
    LOCF <- max(which(!is.na(x))) # the location of the Last Observation to Carry Forward
    x[LOCF:length(x)] <- x[LOCF]
    return(x)
}
# example:
LOCF(c(1,2,3,4,NA,NA))
LOCF(c(1,NA,3,4,NA,NA))
теперь это отлично подходит для простых векторов. Но если я где попробовать и использовать его на фрейме данных:
a <- data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA))
a
t(apply(a, 1, LOCF)) # will make a mess
это превратит мой фрейм данных в символьную матрицу.
можете ли вы придумать способ сделать LOCF на данных.кадр, не превращая его в матрицу? (Я мог бы использовать петли и такие, чтобы исправить беспорядок, но хотел бы более элегантное решение)
спасибо,
Таль
7 ответов
Если вы не хотите загружать большой пакет, такой как zoo, только для na.функция locf, вот короткое решение, которое также работает, если есть некоторые ведущие NAs во входном векторе.
na.locf <- function(x) {
  v <- !is.na(x)
  c(NA, x[v])[cumsum(v)+1]
}
Добавить новый тег tidyr::fill() функция для переноса последнего наблюдения в столбце для заполнения NAs:
a <- data.frame(col1 = rep("a",4), col2 = 1:4, 
                col3 = 1:4, col4 = c(1,NA,NA,NA))
a
#   col1 col2 col3 col4
# 1    a    1    1    1
# 2    a    2    2   NA
# 3    a    3    3   NA
# 4    a    4    4   NA
a %>% tidyr::fill(col4)
#   col1 col2 col3 col4
# 1    a    1    1    1
# 2    a    2    2    1
# 3    a    3    3    1
# 4    a    4    4    1
существует куча пакетов, реализующих именно эту функциональность. (с той же базовой функциональностью, но с некоторыми отличиями в дополнительных опциях)
- пространство-время:: na.locf
- imputeTS:: na.locf
- zoo:: na.locf
- xts:: na.locf
Я закончил решение этого с помощью цикла:
fillInTheBlanks <- function(S) {
  L <- !is.na(S)
  c(S[L][1], S[L])[cumsum(L)+1]
}
LOCF.DF <- function(xx)
{
    # won't work well if the first observation is NA
    orig.class <- lapply(xx, class)
    new.xx <- data.frame(t( apply(xx,1, fillInTheBlanks) ))
    for(i in seq_along(orig.class))
    {
        if(orig.class[[i]] == "factor") new.xx[,i] <- as.factor(new.xx[,i])
        if(orig.class[[i]] == "numeric") new.xx[,i] <- as.numeric(new.xx[,i])
        if(orig.class[[i]] == "integer") new.xx[,i] <- as.integer(new.xx[,i])   
    }
    #t(na.locf(t(a)))
    return(new.xx)
}
a <- data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA))
LOCF.DF(a)
вместо apply() можно использовать lapply() а затем преобразуйте полученный список в data.frame.
LOCF <- function(x) {
    # Last Observation Carried Forward (for a left to right series)
    LOCF <- max(which(!is.na(x))) # the location of the Last Observation to Carry Forward
    x[LOCF:length(x)] <- x[LOCF]
    return(x)
}
a <- data.frame(rep("a",4), 1:4, 1:4, c(1, NA, NA, NA))
a
data.frame(lapply(a, LOCF))
