Функция с cbind, връщаща NA в определени колони

Използвам функция, която идентифицира последователност и след това изчислява продължителността на последователността в минути. Когато обвържа резултатите с данни на последния етап, продължителността се връща, но съседните колони се връщат с „NA“, а не с първоначалните стойности в тези колони

d<-read.table(text='Date.Time Aerial
794  "2012-10-01 08:18:00"      1
795  "2012-10-01 08:34:00"      1
796  "2012-10-01 08:39:00"      1
797  "2012-10-01 08:42:00"      1
798  "2012-10-01 08:48:00"      1
799  "2012-10-01 08:54:00"      1
800  "2012-10-01 08:58:00"      1
801  "2012-10-01 09:04:00"      1
802  "2012-10-01 09:05:00"      1
803  "2012-10-01 09:11:00"      1
1576 "2012-10-01 09:17:00"      2
1577 "2012-10-01 09:18:00"      2
804  "2012-10-01 09:19:00"      1
805  "2012-10-01 09:20:00"      1
1580 "2012-10-01 09:21:00"      2
1581 "2012-10-01 09:23:00"      2
806  "2012-10-01 09:25:00"      1
807  "2012-10-01 09:32:00"      1
808  "2012-10-01 09:37:00"      1
809  "2012-10-01 09:43:00"      1', header=TRUE, stringsAsFactors=FALSE, row.names=1)
#Give correct data type
d$Aerial<- as.numeric(d$Aerial)
d$Date.Time<- as.POSIXct(d$Date.Time)

Функция (идентифицирайте поредица, в която се повтаря антена 2 и продължителността на поредицата):

fun1 <- function(data,aerial){
  data_above <- 1L*(data$Aerial == aerial)
  id_start <- paste(data$Date.Time[which(diff(c(0L,data_above))==1)])
  id_end <- paste(data$Date.Time[which(diff(c(data_above,0L))== -1)])
  res <- cbind(data[id_start,1:1],Duration=difftime(id_end,id_start, units='mins'))
  return(res)
}
fun1(d,2)

Се завръща:

        Duration
[1,] NA        1
[2,] NA        2

Продължителността е правилна, но бих искал да върне данните, които трябва да бъдат в свързаните колони:

     Date.Time                     Duration
[1,] 2012-10-01 09:11:00            1
[2,] 2012-10-01 09:21:00            2

Моят действителен data.frame има много колони, а не само Date.Time и все още връща NA за всички тях


person Salmo salar    schedule 29.03.2013    source източник


Отговори (1)


Бих го направил така:

fun1 <- function(data,aerial) {
    data_above <- 1L * (data$Aerial == aerial)
    id_start <- data$Date.Time[which(diff(c(0L,data_above)) == 1)]
    id_end <- data$Date.Time[which(diff(c(data_above, 0L)) == -1)]
    res <- cbind(data[data$Date.Time %in% id_start, 1, drop=FALSE], 
                  Duration = difftime(id_end,id_start, units='mins'))
   return(res)
}
fun1(d,2)

#                Date.Time Duration
# 1576 2012-10-01 09:17:00   1 mins
# 1580 2012-10-01 09:21:00   2 mins

Точки за отбелязване тук:

  • когато подмножествате data.frame и то връща само 1 елемент, тогава извършването на df[, 1] ще доведе до вектор. Безопасно е да използвате df[, 1, drop = FALSE.

  • Предаването на аргументи, които не са data.frame (което означава, че всички аргументи на cbind не са data.frames) ще доведе до изхода като matrix. Той очаква поне един аргумент да бъде data.frame. Така че, ако не използвате drop = FALSE и резултатът е 1 ред, тогава той ще бъде вектор и резултатът ще бъде матрица (вижте първата точка)

  • Не мисля, че трябва да използвате paste тук за id_start и id_end.

  • Първият аргумент на cbind, където имате достъп до data.frame data, не е правилен. Трябва да направите заявка за id_start във всички стойности на Date.Time. Може да се направи с помощта на %in%, както е показано.

Надявам се това да помогне.

person Arun    schedule 29.03.2013
comment
Това работи перфектно, виждам какво сте направили, има ли шанс да го обясните? - person Salmo salar; 29.03.2013