Разверните категориальный столбец во временном ряду до нескольких столбцов в секунду - PullRequest
4 голосов
/ 22 июля 2011

Каков наилучший способ сделать следующее преобразование?Это преобразование состоит из двух частей.Первый заключается в преобразовании скорости в среднее значение за секунду.Второй - взять категориальный столбец и преобразовать его в несколько столбцов - по одному столбцу на категориальное значение, где значением является количество вхождений в секунду.Например:

Вход (xts A):

Time(PosixCT), Observed Letter, Speed
2011/01/11 12:12:01.100,A,1
2011/01/11 12:12:01.200,A,2
2011/01/11 12:12:01.400,B,3
2011/01/11 12:12:01.800,C,4
2011/01/11 12:12:02.200,D,2
2011/01/11 12:12:02.200,A,7

Выход: (xts B)

Time, A_Per_Second, B_Per_Second, C_Per_Second, D_Per_Second, Aggregate_Speed
2011/01/11 12:12:01,2,1,1,0,2.5
2011/01/11 12:12:02,1,0,0,1,4.5

Я хочу сделать это таким образом, чтобыМне не нужно знать, что все категории.По сути, я пытаюсь сократить время в секунду, не теряя ни одной из моих категорических данных и суммируя числовые данные в среднем за секунду.

Ответы [ 3 ]

3 голосов
/ 22 июля 2011

Вот решение зоопарк .Сначала мы читаем данные, разбивая их на столбец 2. Затем мы усекаем время до секунд и вычисляем количество и сумму.Наконец мы собрали все вместе.

Lines <- "Time(PosixCT), Observed Letter, Speed
2011/01/11 12:12:01.100,A,1
2011/01/11 12:12:01.200,A,2
2011/01/11 12:12:01.400,B,3
2011/01/11 12:12:01.800,C,4
2011/01/11 12:12:02.200,D,2
2011/01/11 12:12:02.200,A,7"

library(zoo)
z <- read.zoo(textConnection(Lines), header = TRUE, sep = ",", split = 2, tz = "")

tt <- as.POSIXct(trunc(time(z), "sec"))
z.knt <- aggregate(z, tt, function(x) sum(!is.na(x)))
z.sum <- aggregate(z, tt, sum, na.rm = TRUE)

cbind(z.knt, Speed = rowSums(z.sum) / rowSums(z.knt))

Результат выглядит так:

                    A B C D Speed
2011-01-11 12:12:01 2 1 1 0   2.5
2011-01-11 12:12:02 1 0 0 1   4.5
3 голосов
/ 22 июля 2011

Я не часто использую данные в формате временных рядов (т.е. xts), поэтому я предоставил решение с использованием данных в формате data.frame.

(Обратите также внимание, что я изменил имена столбцов этого фрейма данных на отдельные слова, чтобы с ним было легче работать. Я публикую структуру своего фрейма данных в конце этого вопроса.)

Я использую два пакета:

  1. HMisc для trunc методов для классов POSIXt
  2. plyr для некоторого волшебства, чтобы разделить, применить и объединить данные

код:

A <- as.data.frame(A)

library(Hmisc)
A$Date <- trunc(A$Date, units="secs")
A

library(plyr)
ddply(A, .(Date, Observed), summarise, Speed=mean(Speed))

результаты в несколько ином формате, чем вы указали, но должно быть легко изменить это в широкий формат, который вы просили.

                 Date Observed Speed
1 2011-01-11 12:12:01        A   1.5
2 2011-01-11 12:12:01        B   3.0
3 2011-01-11 12:12:01        C   4.0
4 2011-01-11 12:12:02        A   7.0
5 2011-01-11 12:12:02        D   2.0

Вот dput результаты A:

A <- structure(list(Date = structure(list(sec = c(1, 1, 1, 1, 2, 2
), min = c(12L, 12L, 12L, 12L, 12L, 12L), hour = c(12L, 12L, 
12L, 12L, 12L, 12L), mday = c(11L, 11L, 11L, 11L, 11L, 11L), 
    mon = c(0L, 0L, 0L, 0L, 0L, 0L), year = c(111L, 111L, 111L, 
    111L, 111L, 111L), wday = c(2L, 2L, 2L, 2L, 2L, 2L), yday = c(10L, 
    10L, 10L, 10L, 10L, 10L), isdst = c(0L, 0L, 0L, 0L, 0L, 0L
    )), .Names = c("sec", "min", "hour", "mday", "mon", "year", 
"wday", "yday", "isdst"), class = c("POSIXlt", "POSIXt"), tzone = c("", 
"GMT", "BST")), Observed = structure(c(1L, 1L, 2L, 3L, 4L, 1L
), .Label = c("A", "B", "C", "D"), class = "factor"), Speed = c(1L, 
2L, 3L, 4L, 2L, 7L)), .Names = c("Date", "Observed", "Speed"), row.names = c(NA, 
-6L), class = "data.frame")
1 голос
/ 22 июля 2011

Вот структура, которую я использую для A.Обратите внимание, что «числа» на самом деле являются символьными, поскольку вы не можете смешивать типы в матрице.

A <- structure(c("A", "A", "B", "C", "D", "A", "1", "2", "3", "4", 
"2", "7"), .Dim = c(6L, 2L), .Dimnames = list(NULL, c("Observed_Letter", 
"Speed")), index = structure(c(1294769521.1, 1294769521.2, 1294769521.4, 
1294769521.8, 1294769522.2, 1294769522.2), tzone = "", tclass = c("POSIXct", 
"POSIXt")), .indexCLASS = c("POSIXct", "POSIXt"), .indexTZ = "",
class = c("xts", "zoo"))

Эта функция очистит каждую из категорий.

clean <- function(x) {
  # construct xts object with only Speed and convert it to numeric
  out <- xts(as.numeric(x$Speed),index(x))
  # add column names
  colnames(out) <- paste(x$Observed_Letter[1],"_Per_Second",sep="")
  out  # return object
}

Воткишки того, что вам нужно.Обратите внимание на необходимость явно указывать split.default, поскольку существует метод split для объектов xts, который разделяется по времени.Вам также не нужно нужно align.time, но он будет округлять каждый период до целой секунды.В противном случае ваш индекс будет последним фактическим значением в индексе за каждую секунду.

# split by Observed_Letter, apply clean() to each list element, and merge results
combA <- do.call(merge, lapply(split.default(A, A$Observed_Letter), clean))
alignA <- align.time(combA,1)
# get the last obs for each 1-second period (for period.apply)
EPalignA <- endpoints(combA, "seconds")
# count the number of non-NA observations by column for each 1-second period
counts <- period.apply(alignA, EPalignA, function(x) colSums(!is.na(x)))
# sum the non-NA observations for each column and 1-second period
values <- period.apply(alignA, EPalignA, colSums, na.rm=TRUE)
# calculate aggregate speed
B <- counts
B$Aggregate_Speed <- rowSums(values)/rowSums(counts)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...