2017-01-22 1 views
0

Еще раз повторю мои предыдущие 2 вопроса, но немного другую проблему. Еще одна морщина в данных, с которыми я работал:использование dplyr с отсутствующими данными

date <- c("2016-03-24","2016-03-24","2016-03-24","2016-03-24","2016-03-24", 
      "2016-03-24","2016-03-24","2016-03-24","2016-03-24") 
location <- c(1,1,2,2,3,3,4,"out","out") 
sensor <- c(1,16,1,16,1,16,1,1,16) 
Temp <- c(35,34,92,42,21,47,42,63,12) 
df <- data.frame(date,location,sensor,Temp) 

Некоторые из моих данных имеют отсутствующие значения. Они не указаны NA. Они просто не в период данных.

Я хочу вычесть местоположение «out» из местоположения «4», игнорируя другие местоположения, и я хочу сделать это по дате и датчику. Я успешно сделал это с местом данных, которые имеют все данные с помощью следующего кода

df %>% 
    filter(location %in% c(4, 'out')) %>% 
    group_by(date, sensor) %>% 
    summarize(Diff = Temp[location=="4"] - Temp[location=="out"], 
      location = first(location)) %>% 
    select(1, 2, 4, 3) 

Однако для данных с отсутствующей датой я получаю следующее сообщение об ошибке Error: expecting a single value. Я думаю, это связано с тем, что dplyr не знает, что делать, когда он достигает недостающей точки данных.

Выполнение некоторых исследований, как представляется, do - это путь, но он возвращает фрейм данных без каких-либо значений, вычитаемых из одного другого.

df %>% 
    filter(location %in% c(4, 'out')) %>% 
    group_by(date, sensor) %>% 
    do(Diff = Temp[location=="4"] - Temp[location=="out"], 
      location = first(location)) %>% 
    select(1, 2, 4, 3) 

Есть ли способ, чтобы переопределить dplyr и сказать ему, чтобы вернуть NA, если он не может найти одну из записей вычитать?

+0

Btw, я получаю ту же ошибку для ваших данных, даже хотя нет никаких дат даты! – Rahul

+0

отсутствуют значения – hrbrmstr

ответ

1

Если мы хотим вернуть NA, возможный вариант

library(dplyr) 
df %>% 
    filter(location %in% c(4, 'out')) %>% 
    group_by(date, sensor) %>% 
    arrange(sensor, location) %>% 
    summarise(Diff = if(n()==1) NA else diff(Temp), location = first(location)) %>% 
    select(1, 2, 4, 3) 
#  date sensor location Diff 
#  <fctr> <dbl> <fctr> <dbl> 
#1 2016-03-24  1  4 21 
#2 2016-03-24  16  out NA 

и эквивалентный вариант в data.table является

library(data.table) 
setDT(df)[location %in% c(4, 'out')][ 
    order(sensor, location), .(Diff = if(.N==1) NA_real_ else diff(Temp), 
     location = location[1]), .(date, sensor)][, c(1, 2, 4, 3), with = FALSE] 
#   date sensor location Diff 
#1: 2016-03-24  1  4 21 
#2: 2016-03-24  16  out NA 
3
library(tidyverse) 

date <- c("2016-03-24", "2016-03-24", "2016-03-24", "2016-03-24", "2016-03-24", 
      "2016-03-24", "2016-03-24", "2016-03-24", "2016-03-24") 
location <- c(1, 1, 2, 2, 3, 3, 4, "out", "out") 
sensor <- c(1, 16, 1, 16, 1, 16, 1, 1, 16) 
Temp <- c(35, 34, 92, 42, 21, 47, 42, 63, 12) 

df <- data_frame(date, location, sensor, Temp) 

# edge case helper 
`%||0%` <- function (x, y) { if (is.null(x) | length(x) == 0) y else x } 

df %>% 
    filter(location %in% c(4, 'out')) %>% 
    mutate(location=factor(location, levels=c("4", "out"))) %>%    # make location a factor 
    arrange(sensor, location) %>%           # order it so we can use diff() 
    group_by(date, sensor) %>% 
    summarize(Diff = diff(Temp) %||0% NA, location = first(location)) %>% # deal with the edge case 
    select(1, 2, 4, 3) 
## Source: local data frame [2 x 4] 
## Groups: date [1] 
## 
##   date sensor location Diff 
##  <chr> <dbl> <fctr> <dbl> 
## 1 2016-03-24  1  4 21 
## 2 2016-03-24  16  out NA