O que é um método eficiente para particionar e agregar intervalos de linhas timestamped em um quadro de dados?

StackOverflow https://stackoverflow.com/questions/2441136

  •  19-09-2019
  •  | 
  •  

Pergunta

A partir de um quadro de dados com linhas timestamped (resultados strptime), o que é o melhor método para agregar estatísticas para intervalos?

Intervalos poderia ser uma hora, um dia, etc

Há a função aggregate, mas isso não ajudar com a atribuição de cada linha para um intervalo. Estou pensando em adicionar uma coluna para o quadro de dados que denota intervalo e usando isso com aggregate, mas se há uma solução melhor seria ótimo para ouvi-lo.

Obrigado por qualquer ponteiros!


Exemplo de Dados

Cinco linhas com marcas de tempo dividido em intervalos de 15 minutos a partir de 03:00.

Intervalo 1

  • "2010-01-13 03:02:38 UTC"
  • "2010-01-13 03:08:14 UTC"
  • "2010-01-13 03:14:52 UTC"

Intervalo 2

  • "2010-01-13 03:20:42 UTC"
  • "2010-01-13 03:22:19 UTC"

Conclusão

Usando um pacote de séries temporais, como xts deve ser a solução; porém eu não teve sucesso usá-los e fôlego até usando cut. Como eu atualmente só precisa histogramas enredo, com linhas agrupadas por intervalo, este foi o suficiente.

cut é usado gostou:

interv <- function(x, start, period, num.intervals) {
  return(cut(x, as.POSIXlt(start)+0:num.intervals*period))
}
Foi útil?

Solução

As funções padrão para vetores de divisão são cut e findInterval:

v <- as.POSIXct(c(
  "2010-01-13 03:02:38 UTC",
  "2010-01-13 03:08:14 UTC",
  "2010-01-13 03:14:52 UTC",
  "2010-01-13 03:20:42 UTC",
  "2010-01-13 03:22:19 UTC"
))

# Your function return list:
interv(v, as.POSIXlt("2010-01-13 03:00:00 UTC"), 900)
# [[1]]
# [1] "2010-01-13 03:00:00"
# [[2]]
# [1] "2010-01-13 03:00:00"
# [[3]]
# [1] "2010-01-13 03:00:00"
# [[4]]
# [1] "2010-01-13 03:15:00 CET"
# [[5]]
# [1] "2010-01-13 03:15:00 CET"

# cut returns factor, you must provide proper breaks:
cut(v, as.POSIXlt("2010-01-13 03:00:00 UTC")+0:2*900)
# [1] 2010-01-13 03:00:00 2010-01-13 03:00:00 2010-01-13 03:00:00
# [4] 2010-01-13 03:15:00 2010-01-13 03:15:00
# Levels: 2010-01-13 03:00:00 2010-01-13 03:15:00

# findInterval returns vector of interval id (breaks like in cut)
findInterval(v, as.POSIXlt("2010-01-13 03:00:00 UTC")+0:2*900)
# [1] 1 1 1 2 2

Para o registro: cut tem um método para o tipo POSIXt, mas infelizmente não há nenhuma maneira de fornecer argumento start, o efeito é:

cut(v,"15 min")
# [1] 2010-01-13 03:02:00 2010-01-13 03:02:00 2010-01-13 03:02:00
# [4] 2010-01-13 03:17:00 2010-01-13 03:17:00
# Levels: 2010-01-13 03:02:00 2010-01-13 03:17:00

Como você vê o seu inicio em 3:02:00. Você poderia mexer com etiquetas de factor de saída (etiquetas converter-se ao tempo, rodada de alguma forma e converter de volta para personagem).

Outras dicas

Use a pacote de séries temporais. O pacote XTS tem funções projetado especificamente para fazer isso. Ou olhar para as funções agregadas e rollapply no pacote zoológico.

O ebook rmetrics tem uma discussão útil, incluindo uma comparação dos vários pacotes de desempenho: https://www.rmetrics.org/files/freepdf/TimeSeriesFAQ.pdf

Editar : Olhe para minha resposta a esta pergunta . Basicamente, você precisa truncar cada timestamp em um intervalo específico e, em seguida, fazer a agregação usando esses novos timestamps truncados como seu vetor de agrupamento.

Esta é uma pergunta interessante; com a proliferação dos vários pacotes de séries temporais e métodos, deve haver uma abordagem para binning série temporal irregular e não pela força bruta que o OP sugere. Aqui está uma maneira "de alto nível" para obter os intervalos que você pode usar para aggregate et al, usando uma versão do cut definido para objetos chron.

require(chron)
require(timeSeries)

my.times <- "
2010-01-13 03:02:38 UTC
2010-01-13 03:08:14 UTC
2010-01-13 03:14:52 UTC
2010-01-13 03:20:42 UTC
2010-01-13 03:22:19 UTC
"

time.df <- read.delim(textConnection(my.times),header=FALSE,sep="\n",strip.white=FALSE)
time.seq <- seq(trunc(timeDate(time.df[1,1]),units="hours"),by=15*60,length=nrow(time.df))
intervals <- as.numeric(cut(as.chron(as.character(time.df$V1)),breaks=as.chron(as.character(time.seq))))

Você começa

intervals  
[1] 1 1 1 2 2

que agora você pode anexar ao quadro de dados e agregados.

As acrobacias coersion acima (de personagem para TimeDate a personagem para chron) é um pouco infeliz, por isso, se há soluções mais limpas para binning dados tempo irregulares usando XTS ou qualquer um dos outros pacotes TimeSeries, eu adoraria ouvir sobre -los também! ..

Também estou curioso para saber o que seria a abordagem mais eficiente para binning série temporal irregular larga de alta frequência, por exemplo, a criação de barras de volume de 1 minuto em dados de carrapatos para um estoque muito líquido.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top