Перебирать столбец, игнорируя, но сохраняя значения NA в R - PullRequest
0 голосов
/ 28 августа 2018

У меня есть кадр данных временного ряда в R, который имеет столбец V1, который состоит из целых чисел с несколькими NA, разбросанными по всему. Я хочу перебрать этот столбец и вычесть V1 из себя за один шаг ранее. Однако я хочу игнорировать значения NA в V1 и использовать последнее не-значение NA в вычитании. Если текущее значение V1 равно NA, тогда разница должна возвращать NA. Ниже приведен пример

V1 <- c(1, 3, 4, NA, NA, 6, 9, NA, 10)
time <- 1:length(V1)
dat <- data.frame(time = time,
                     V1 = V1)
lag_diff <- c(NA, 2, 1, NA, NA, 2, 3, NA, 1) # The result I want
diff(dat$V1) # Not the result I want

Я бы предпочел не делать это с циклами, потому что у меня есть сотни фреймов данных, каждый с> 10000 строк.

Моей первой мыслью для решения этой проблемы было отфильтровать строки NA, выполнить итеративный расчет разности, а затем повторно вставить отфильтрованные строки, но я не могу придумать, как это сделать. Это тоже не выглядит очень аккуратно, и я не уверен, что это будет быстрее, чем зацикливание. Любая помощь приветствуется, бонусные баллы, если решение использует функции Tidyverse.

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Tidyverse версия, на всякий случай. Это действительно нужно filter хотя

dat %>% 
  filter(!is.na(V1)) %>% 
  mutate(diff=V1- lag(V1)) %>% 
  right_join(dat,by=c("time","V1"))
0 голосов
/ 28 августа 2018
dat[!is.na(dat$V1), 'lag_diff'] <- c(NA, diff(dat[!is.na(dat$V1), 'V1']))
#   time V1 lag_diff
# 1    1  1       NA
# 2    2  3        2
# 3    3  4        1
# 4    4 NA       NA
# 5    5 NA       NA
# 6    6  6        2
# 7    7  9        3
# 8    8 NA       NA
# 9    9 10        1

Или с data.table (тот же результат)

library(data.table)
setDT(dat)

dat[!is.na(V1), lag_diff := V1 - shift(V1)]

#    time V1 lag_diff
# 1:    1  1       NA
# 2:    2  3        2
# 3:    3  4        1
# 4:    4 NA       NA
# 5:    5 NA       NA
# 6:    6  6        2
# 7:    7  9        3
# 8:    8 NA       NA
# 9:    9 10        1
...