Come aggregare per minuto i dati per una settimana in mezzi orari?


15

Come otterresti le medie orarie per più colonne di dati, per un periodo giornaliero, e mostrerai i risultati per dodici "Host" nello stesso grafico? Cioè, vorrei rappresentare graficamente l'aspetto di un periodo di 24 ore, per una settimana di dati. L'obiettivo finale sarebbe quello di confrontare due serie di questi dati, prima e dopo i campionamenti.

            dates         Host CPUIOWait CPUUser CPUSys
1 2011-02-11 23:55:12     db       0      14      8
2 2011-02-11 23:55:10     app1     0       6      1
3 2011-02-11 23:55:09     app2     0       4      1

Sono stato in grado di eseguire xyplot (CPUUser ~ date | Host) con buoni risultati. Tuttavia, piuttosto che mostrare ogni data della settimana, vorrei che l'asse X fosse l'ora del giorno.

Cercare di ottenere questi dati in un oggetto xts genera errori come "order.by richiede un oggetto basato sul tempo appropriato"

Ecco uno str () del frame di dati:

'data.frame':   19720 obs. of  5 variables:
$ dates    : POSIXct, format: "2011-02-11 23:55:12" "2011-02-11 23:55:10" ...
$ Host     : Factor w/ 14 levels "app1","app2",..: 9 7 5 4 3 10 6 8 2 1 ...  
$ CPUIOWait: int  0 0 0 0 0 0 0 0 0 0 ...
$ CPUUser  : int  14 6 4 4 3 10 4 3 4 4 ...
$ CPUSys   : int  8 1 1 1 1 3 1 1 1 1 ...

AGGIORNAMENTO: Solo per riferimento futuro, ho deciso di andare con un diagramma a scatole, per mostrare sia la mediana, sia i "valori anomali".

Essenzialmente:

Data$hour <- as.POSIXlt(dates)$hour  # extract hour of the day
boxplot(Data$CPUUser ~ Data$hour)    # for a subset with one host or for all hosts
xyplot(Data$CPUUser ~ Data$hour | Data$Host, panel=panel.bwplot, horizontal=FALSE)

Grazie


Immagino tu riceva quegli errori xts()perché la datescolonna è un fattore.
Joshua Ulrich,

Sono davvero nuovo di R ... Ho creato la colonna delle date dalla funzione strptime. I dati originali provengono da read.csv.
Scott Hoffman,

1
Vediamo str()data.frame.
Roman Luštrik,

@Roman Grazie per la funzione str (), non ne ero a conoscenza. Quindi, liberandomi della colonna Fattore, posso generare un oggetto xts come questo, x <-xts (d [, 3: 5], order.by = d [, 1]). Sono stato quindi in grado di applicare a. Hourly, che accorcia i dati da 19720 oggetti fino a 480. Non sono sicuro se questo mi porterà dove voglio, ma sono più vicino ora, penso.
Scott Hoffman,

Risposte:


14

Ecco un approccio che utilizza cut () per creare i fattori orari appropriati e ddply () dalla libreria plyr per calcolare le medie.

library(lattice)
library(plyr)

## Create a record and some random data for every 5 seconds 
## over two days for two hosts.
dates <- seq(as.POSIXct("2011-01-01 00:00:00", tz = "GMT"),
             as.POSIXct("2011-01-02 23:59:55", tz = "GMT"),
             by = 5)
hosts <- c(rep("host1", length(dates)), rep("host2", 
           length(dates)))
x1    <- sample(0:20, 2*length(dates), replace = TRUE)
x2    <- rpois(2*length(dates), 2)
Data  <- data.frame(dates = dates, hosts = hosts, x1 = x1, 
                    x2 = x2)

## Calculate the mean for every hour using cut() to define 
## the factors and ddply() to calculate the means. 
## getmeans() is applied for each unique combination of the
## hosts and hour factors.
getmeans  <- function(Df) c(x1 = mean(Df$x1), 
                            x2 = mean(Df$x2))
Data$hour <- cut(Data$dates, breaks = "hour")
Means <- ddply(Data, .(hosts, hour), getmeans)
Means$hour <- as.POSIXct(Means$hour, tz = "GMT")

## A plot for each host.
xyplot(x1 ~ hour | hosts, data = Means, type = "o",
       scales = list(x = list(relation = "free", rot = 90)))

Grazie per questo ... penso che potrei aver bisogno di riformulare la domanda o di farne una nuova. Guardando questa domanda stats.stackexchange.com/questions/980/… , ora penso che ottenere i mezzi non sia esattamente quello che sto cercando .
Scott Hoffman,

@JVM Puoi spiegare come funziona la funzione getmeans e perché non hai usato solo le funzioni mean o colMeans?
Scott Hoffman,

1
La funzione ddply () taglia il set di dati originale in sottoinsiemi definiti da host e ora. Quindi li passa a getmeans () come data.frame. Per la tua attività, usare colMeans () probabilmente funzionerebbe bene, ma probabilmente dovrai prima rimuovere le colonne che non ti servono. La cosa bella dell'uso di ddply () in questo modo è che puoi calcolare qualsiasi stat arbitraria per la quale potresti essere interessato; ad esempio, sd (), range (), ecc.
Jason Morgan,

6

L'aggregazione funziona anche senza usare zoo(con dati casuali da 2 variabili per 3 giorni e 4 host come da JWM). Presumo che tu abbia dati da tutti gli host per ogni ora.

nHosts <- 4  # number of hosts
dates  <- seq(as.POSIXct("2011-01-01 00:00:00"),
              as.POSIXct("2011-01-03 23:59:30"), by=30)
hosts  <- factor(sample(1:nHosts, length(dates), replace=TRUE),
                 labels=paste("host", 1:nHosts, sep=""))
x1     <- sample(0:20, length(dates), replace=TRUE)  # data from 1st variable
x2     <- rpois(length(dates), 2)                    # data from 2nd variable
Data   <- data.frame(dates=dates, hosts=hosts, x1=x1, x2=x2)

Non sono del tutto sicuro se vuoi fare la media solo entro ogni ora o entro ogni ora per tutti i giorni. Farò entrambe le cose.

Data$hFac <- droplevels(cut(Data$dates, breaks="hour"))
Data$hour <- as.POSIXlt(dates)$hour  # extract hour of the day

# average both variables over days within each hour and host
# formula notation was introduced in R 2.12.0 I think
res1 <- aggregate(cbind(x1, x2) ~ hour + hosts, data=Data, FUN=mean)
# only average both variables within each hour and host
res2 <- aggregate(cbind(x1, x2) ~ hFac + hosts, data=Data, FUN=mean)

Il risultato è simile al seguente:

> head(res1)
  hour hosts        x1       x2
1    0 host1  9.578431 2.049020
2    1 host1 10.200000 2.200000
3    2 host1 10.423077 2.153846
4    3 host1 10.241758 1.879121
5    4 host1  8.574713 2.011494
6    5 host1  9.670588 2.070588

> head(res2)
                 hFac hosts        x1       x2
1 2011-01-01 00:00:00 host1  9.192308 2.307692
2 2011-01-01 01:00:00 host1 10.677419 2.064516
3 2011-01-01 02:00:00 host1 11.041667 1.875000
4 2011-01-01 03:00:00 host1 10.448276 1.965517
5 2011-01-01 04:00:00 host1  8.555556 2.074074
6 2011-01-01 05:00:00 host1  8.809524 2.095238

Inoltre, non sono del tutto sicuro del tipo di grafico che desideri. Ecco la versione bare-bones di un grafico solo per la prima variabile con righe di dati separate per ciascun host.

# using the data that is averaged over days as well
res1L <- split(subset(res1, select="x1"), res1$hosts)
mat1  <- do.call(cbind, res1L)
colnames(mat1) <- levels(hosts)
rownames(mat1) <- 0:23
matplot(mat1, main="x1 per hour, avg. over days", xaxt="n", type="o", pch=16, lty=1)
axis(side=1, at=seq(0, 23, by=2))
legend(x="topleft", legend=colnames(mat1), col=1:nHosts, lty=1)

Lo stesso grafico per i dati calcolato in media solo ogni ora.

res2L <- split(subset(res2, select="x1"), res2$hosts)
mat2  <- do.call(cbind, res2L)
colnames(mat2) <- levels(hosts)
rownames(mat2) <- levels(Data$hFac)
matplot(mat2, main="x1 per hour", type="o", pch=16, lty=1)
legend(x="topleft", legend=colnames(mat2), col=1:nHosts, lty=1)

Bella risposta, un sacco di cose che non conosco, quindi devo provarlo. Tuttavia, guardando i miei dati con i tuoi metodi, sto pensando di dover mostrare anche i punti più alti dei miei dati. Grazie
Scott Hoffman,

2

È possibile effettuare il checkout della aggregate.zoofunzione dal pacchetto zoo: http://cran.r-project.org/web/packages/zoo/zoo.pdf

Charlie


Puoi aiutarmi a capire perché ricevo NA quando eseguo questo?
Scott Hoffman,

Ciao Scott, non ho usato la aggregate.zoofunzione, anche se ho usato il zoopacchetto. Ti sei assicurato che il tuo oggetto fosse zooprima un oggetto? La documentazione che ho indicato dovrebbe aiutarti.
Charlie,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.