Ближайшее значение, отличное от NA

#r #dplyr #data.table #zoo

#r #dplyr #данные.таблица #зоопарк

Вопрос:

У меня есть фрейм данных test

 > test
   foo  bar  baz  timestamp
1    1 <NA>    a 1552157998
2    1 <NA> <NA> 1552161596
3    1 stop <NA> 1552165194
4    1 <NA>    b 1552168795
5    1 <NA>    a 1552170839
6    1 <NA> <NA> 1552157998
7    1 stop <NA> 1552161596
8    1 <NA>    a 1552165194
9    1 <NA>    b 1552168795
10   1 <NA> <NA> 1552170839
 

Моя цель — найти для каждого экземпляра stop ближайшее значение, отличное от NA, в каждом направлении (на основе timestamp ), которое создало бы таблицу, подобную этой:

 > output
  rownum pre post
1      3   a    b
2      7   a    a
 

Есть ли известный способ сделать это с zoo помощью and na.locf() ?

Любые предложения будут оценены

 dput(test)
structure(list(foo = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), bar = c(NA, 
NA, "stop", NA, NA, NA, "stop", NA, NA, NA), baz = c("a", NA, 
NA, "b", "a", NA, NA, "a", "b", NA), timestamp = c(1552157998.427, 
1552161596.004, 1552165194.255, 1552168794.918, 1552170839.363, 
1552157998.427, 1552161596.004, 1552165194.255, 1552168794.918, 
1552170839.363)), row.names = c(NA, -10L), class = "data.frame")
 

Комментарии:

1. Не могли бы вы включить timestamp столбец в свой dput ?

2. да, я это сделал — отредактировано

3. Использует ли последующие элементы один и тот же pre / post?

4. @akrun да, то же самое

5. Поскольку вы упомянули «на основе метки времени»: предполагается ли упорядочивать набор данных перед определением следующего / предыдущего элемента. Потому что я получаю другой результат, если это так

Ответ №1:

Я буду использовать magrittr исключительно для организации кода. Это можно так же легко перевести в не- magrittr , dplyr , или data.table с минимальными усилиями.

 library(magrittr)
test %>%
  .[ order(.$timestamp), ] %>%
  transform(.,
            rownum = seq_len(nrow(.)),
            pre = zoo::na.locf0(baz),
            post = zoo::na.locf0(baz, fromLast = TRUE)) %>%
  subset(., bar == "stop") %>%
  .[, c("rownum", "pre", "post")]
#   rownum pre post
# 7      4   a    a
# 3      5   a    a
 

(Это отличается от ожидаемого результата, возможно, потому, что это ошибка?)

Вы можете немного лучше понять, что это делает, посмотрев на него раньше subset :

 test %>%
  .[ order(.$timestamp), ] %>%
  transform(.,
            rownum = seq_len(nrow(.)),
            pre = zoo::na.locf0(baz),
            post = zoo::na.locf0(baz, fromLast = TRUE))
#    foo  bar  baz  timestamp rownum pre post
# 1    1 <NA>    a 1552157998      1   a    a
# 6    1 <NA> <NA> 1552157998      2   a    a
# 2    1 <NA> <NA> 1552161596      3   a    a
# 7    1 stop <NA> 1552161596      4   a    a
# 3    1 stop <NA> 1552165194      5   a    a
# 8    1 <NA>    a 1552165194      6   a    a
# 4    1 <NA>    b 1552168795      7   b    b
# 9    1 <NA>    b 1552168795      8   b    b
# 5    1 <NA>    a 1552170839      9   a    a
# 10   1 <NA> <NA> 1552170839     10   a <NA>
 

Комментарии:

1. Если я закажу data.frame здесь, я получу другой результат: post равно «a» для обоих индексов.

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

3. Я не предоставил никакого образца. Ваш код здесь не работает, потому что он не будет упорядочен по временной метке test[order(timestamp),] test[order(test$timestamp),] , иначе он выдаст ошибку и не отсортирует df перед выполнением rest // PS: на самом деле это не проблема с вашим кодом (помимо проблемы с упорядочением), я думаю, что желаемый результат ОПЕРАЦИИ просто неправильно для упорядоченного df.