Перенести последнее наблюдение вперед по идентификатору в R

У меня есть ежедневные наблюдения с множеством пропущенных значений, и я пытаюсь передать первое не пропущенное значение через вектор для каждого человека.

В ходе поиска, который я проделал до сих пор, я обнаружил функцию na.locf в пакете zoo; однако теперь мне нужно настроить эту функцию на основе переменной id в моем фрейме данных. Подходит ли ddply функция для этого? Если да, может ли кто-нибудь мне помочь, пожалуйста, выясните, как включить вывод в новую переменную с именем result в том же фрейме данных?

Вот что у меня есть на данный момент:

# Load required libraries
library(zoo)
library(plyr)

# Create the data
data <- structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 
              2, 2, 2), day = c(0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7, 
              8), value = c("NA", "1", "NA", "NA", "NA", "NA", "NA", "NA", 
              "NA", "NA", "1", "NA", "NA", "NA", "NA", "NA")), .Names = c("id", 
              "day", "value"), row.names = c(NA, -16L), class = "data.frame")

# Propagate the value of the first non-missing observation in data$value forward for each id
data$result <- na.locf(data$value, na.rm = FALSE)

Приветствуются любые мысли о том, как запускать функцию na.locf каждым id. Спасибо!


r na zoo
person Entropy    schedule 22.05.2014    source источник


Ответы (1)


1) Во-первых, обратите внимание, что столбец value является символьным столбцом со значениями "NA", а не значениями NA, поэтому давайте сначала исправим это в ##. Затем создайте функцию-оболочку na.locf.na, которая использует na.locf в пакете zoo и остается такой же, за исключением значений по умолчанию к na.rm = FALSE. Наконец, используйте ave, чтобы применить na.locf до id:

library(zoo)

data2 <- transform(data, value = as.numeric(value)) ##

na.locf.na <- function(x, na.rm = FALSE, ...) na.locf(x, na.rm = na.rm, ...)
transform(data2, value = ave(value, id, FUN = na.locf.na))

2) или эту компактную альтернативу с использованием fn из пакета gsubfn для более компактного представления na.locf.na inline:

library(zoo)
library(gsubfn)

transform(data2, value = fn$ave(value, id, FUN = ~ na.locf(x, na.rm = FALSE)))

В любом из этих двух случаев результат будет следующим:

   id day value
1   1   0    NA
2   1   1     1
3   1   2     1
4   1   3     1
5   1   4     1
6   1   5     1
7   1   6     1
8   2   0    NA
9   2   1    NA
10  2   2    NA
11  2   3     1
12  2   4     1
13  2   5     1
14  2   6     1
15  2   7     1
16  2   8     1

3) Мы могли бы альтернативно использовать dplyr вместе с zoo, используя na.locf.na сверху:

library(zoo)
library(dplyr)

data2 <- data %>% mutate(value = as.numeric(value)) # fix value column
data2 %>% group_by(id) %>% mutate(value = na.locf.na(value))

Если dplyr from CRAN здесь не работает, попробуйте вариант с github:

library(devtools)
install_github("hadley/dplyr")

ИСПРАВЛЕНИЯ Реорганизованная презентация и добавленные альтернативы.

person G. Grothendieck    schedule 22.05.2014
comment
Абсолютно идеально - спасибо! Я никогда раньше не использовал функцию transform, но обязательно изучу ее дальше. Еще раз спасибо. - person Entropy; 23.05.2014