2015-07-16 2 views
3

У меня есть кадр данных с отсутствующими значениями для «SNAP_ID». Я хотел бы заполнить недостающие значения значениями с плавающей запятой на основе последовательности из предыдущего не пропущенного значения (lag()?). Я бы очень хотел добиться этого, используя только dplyr, если это возможно.Заполнить недопустимые значения последовательности с помощью dplyr

Предположения:

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

Текущие данные:

    end SNAP_ID 
1 2015-06-26 12:59:00  365 
2 2015-06-26 13:59:00  366 
3 2015-06-27 00:01:00  NA 
4 2015-06-27 23:00:00  NA 
5 2015-06-28 00:01:00  NA 
6 2015-06-28 23:00:00  NA 
7 2015-06-29 09:00:00  367 
8 2015-06-29 09:59:00  368 

W Шляпа я хочу добиться:

    end SNAP_ID 
1 2015-06-26 12:59:00  365.0 
2 2015-06-26 13:59:00  366.0 
3 2015-06-27 00:01:00  366.1 
4 2015-06-27 23:00:00  366.2 
5 2015-06-28 00:01:00  366.3 
6 2015-06-28 23:00:00  366.4 
7 2015-06-29 09:00:00  367.0 
8 2015-06-29 09:59:00  368.0 

В кадре данных:

df <- structure(list(end = structure(c(1435323540, 1435327140, 1435363260, 
    1435446000, 1435449660, 1435532400, 1435568400, 1435571940), tzone = "UTC", class = c("POSIXct", 
    "POSIXt")), SNAP_ID = c(365, 366, NA, NA, NA, NA, 367, 368)), .Names = c("end", 
    "SNAP_ID"), row.names = c(NA, -8L), class = "data.frame") 

Это была моя попытка достичь этой цели, но он работает только для первого отсутствующего значения:

df %>% 
    arrange(end) %>% 
    mutate(SNAP_ID=ifelse(is.na(SNAP_ID),lag(SNAP_ID)+0.1,SNAP_ID)) 

        end SNAP_ID 
1 2015-06-26 12:59:00 365.0 
2 2015-06-26 13:59:00 366.0 
3 2015-06-27 00:01:00 366.1 
4 2015-06-27 23:00:00  NA 
5 2015-06-28 00:01:00  NA 
6 2015-06-28 23:00:00  NA 
7 2015-06-29 09:00:00 367.0 
8 2015-06-29 09:59:00 368.0 

Выдающийся ответ от @ Mathematical.coffee ниже:

ответ

5

EDIT: новая версия работает для любого количества прогонов NA. Этот не нужен zoo, либо.

Во-первых, обратите внимание, что tmp=cumsum(!is.na(SNAP_ID)) групп SNAP_ID s такие группы из них tmp состоят из одного значения, отличного от NA, за которым следует пробег значений NA.

Тогда группа этой переменной и просто добавить .1 к первому SNAP_ID заполнить Nas:

df %>% 
    arrange(end) %>% 
    group_by(tmp=cumsum(!is.na(SNAP_ID))) %>% 
    mutate(SNAP_ID=SNAP_ID[1] + 0.1*(0:(length(SNAP_ID)-1))) 

        end SNAP_ID tmp 
1 2015-06-26 12:59:00 365.0 1 
2 2015-06-26 13:59:00 366.0 2 
3 2015-06-27 00:01:00 366.1 2 
4 2015-06-27 23:00:00 366.2 2 
5 2015-06-28 00:01:00 366.3 2 
6 2015-06-28 23:00:00 366.4 2 
7 2015-06-29 09:00:00 367.0 3 
8 2015-06-29 09:59:00 368.0 4 

Затем вы можете уронить tmp колонку впоследствии (добавить %>% select(-tmp) до конца).


EDIT: это старая версия, которая не работает на последующих запусках NA с.

Если ваша цель состоит в том, чтобы заполнить каждый NA с предыдущим значением + 0,1, вы можете использовать zoo «s na.locf (который заполняет каждый NA с предыдущим значением), наряду с cumsum(is.na(SNAP_ID))*0.1 добавить дополнительные 0,1.

library(zoo) 
df %>% 
    arrange(end) %>% 
    mutate(SNAP_ID=ifelse(is.na(SNAP_ID), 
         na.locf(SNAP_ID) + cumsum(is.na(SNAP_ID))*0.1, 
         SNAP_ID)) 
+1

Спасибо за выдающийся ответ! Единственная незначительная коррекция - вам нужно разгруппировать() перед выбором (-tmp). ungroup() иногда меня заводит. –

Смежные вопросы