2016-07-29 8 views
1

У меня есть набор пар наблюдений, которые я хочу обозначить интервалами между их time. (В реальных данных, эти пары наблюдений представляют вход и выход для микрофона калибровок.)Группировка dplyr :: mutate неверно возвращает векторы интервалов lubridate

# R version 3.2.3 
library(lubridate) ## Version 1.5.6 
library(dplyr) ## Version 0.5.0 

data <- data.frame(
    group = c(1,1,2,2,3,3), 
    type = rep(c("start", "end"), 3), 
    time = ymd_hms("2016-06-01 01:00:00") + c(0,1,3,6,12,18), 
    someAttribute = runif(6) 
) 

data 
## group type    time someAttribute 
## 1  1 start 2016-06-01 01:00:00  0.2540128 
## 2  1 end 2016-06-01 01:00:01  0.6845078 
## 3  2 start 2016-06-01 01:00:03  0.3576477 
## 4  2 end 2016-06-01 01:00:06  0.1223582 
## 5  3 start 2016-06-01 01:00:12  0.2715063 
## 6  3 end 2016-06-01 01:00:18  0.6392607 

включает фиктивный someAttribute в этом примере, чтобы подчеркнуть, что простое решение, как tidyr::spread() бы напутать атрибуты, которые принадлежат каждая строка в data.

У меня есть функция, которая делает интервалы, и я применяю его группой с dplyr:

makeTwoIntervals <- function(twoDatetimes) { 
    return(rep(interval(twoDatetimes[1], twoDatetimes[2]), 2)) 
} 

data2 <- data %>% group_by(group) %>% mutate(intervals = makeTwoIntervals(time)) 

data2$intervals 
## [1] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:01 UTC 
## [2] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:01 UTC 
## [3] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:03 UTC 
## [4] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:03 UTC 
## [5] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:06 UTC 
## [6] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:06 UTC 

Эти значения не то, что я ожидал получить. Правильные времена передаются моей функции, и она создает правильный двухэлементный вектор интервалов для возврата, но когда этот вектор передается обратно в mutate, происходит что-то плохое. Более подробно:

str(data2$intervals) 
## Formal class 'Interval' [package "lubridate"] with 3 slots 
## [email protected] .Data: num [1:6] 1 1 3 3 6 6 
## [email protected] start: POSIXct[1:2], format: "2016-06-01 01:00:00" "2016-06-01 01:00:00" 
## [email protected] tzone: chr "UTC" 

Непонятно мне, что здесь не так. Таковы результаты, которые я хотел увидеть:

## Desired result of data2$intervals: 
## [1] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:01 UTC 
## [2] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:01 UTC 
## [3] 2016-06-01 01:00:03 UTC--2016-06-01 01:00:06 UTC 
## [4] 2016-06-01 01:00:03 UTC--2016-06-01 01:00:06 UTC 
## [5] 2016-06-01 01:00:12 UTC--2016-06-01 01:00:18 UTC 
## [6] 2016-06-01 01:00:12 UTC--2016-06-01 01:00:18 UTC 

Может кто-нибудь предложить некоторое понимание того, что пошло не так, и как я мог бы достичь желаемого результата? Я неправильно использую mutate, или он просто не предназначен для обработки таких объектов, как lubridate::Interval?

+0

Это было недавно зарегистрировано как проблема [# 1777] (https://github.com/Rdatatable/data.table/issues/1777) на странице проекта data.table, а также я предлагаю обходной путь там , – Arun

ответ

1

Это временное решение основано на @data.table обходного Аруна (#1777), но в dplyr языке:

data2 <- data %>% group_by(group) %>% mutate(ranges = list(range(time))) 
data3 <- data2 %>% mutate(intervals = list(interval(ranges[[1]][1], ranges[[1]][2]))) 
data3$intervals2 <- do.call("c", data3$intervals) 

data3$intervals2 
## [1] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:01 UTC 
## [2] 2016-06-01 01:00:00 UTC--2016-06-01 01:00:01 UTC 
## [3] 2016-06-01 01:00:03 UTC--2016-06-01 01:00:06 UTC 
## [4] 2016-06-01 01:00:03 UTC--2016-06-01 01:00:06 UTC 
## [5] 2016-06-01 01:00:12 UTC--2016-06-01 01:00:18 UTC 
## [6] 2016-06-01 01:00:12 UTC--2016-06-01 01:00:18 UTC 

не полностью удовлетворяет, но это работает. Спасибо за подсказку @Arun.