Як узагальнити дані за хвилину за тиждень у погодинний засіб?


15

Як би ви отримали погодинний засіб для декількох стовпців даних за щоденний період та показували результати для дванадцяти "хостів" в одному графіку? Тобто, я хотів би накреслити, як виглядає 24-годинний період, на тижні даних. Можливою метою буде порівняння двох наборів цих даних до та після вибірки.

            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

Мені вдалося запустити xyplot (CPUUser ~ дати | Хост) з хорошим ефектом. Однак, замість того, щоб показувати кожну дату на тижні, я хотів би, щоб вісь X була годиною дня.

Спроба отримати ці дані в об’єкт xts призводить до помилок, таких як "order.by вимагає відповідного об'єкту на основі часу".

Ось str () кадру даних:

'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 ...

ОНОВЛЕННЯ: Тільки для подальшого ознайомлення я вирішив поїхати з боксертом, щоб показати як медіану, так і «людей, що вижили».

По суті:

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)

Спасибі


Я здогадуюсь, ви отримуєте ці помилки, xts()оскільки datesстовпець є фактором.
Джошуа Ульріх

Я дійсно новачок у R ... Я створив стовпчик дат із функції strptime. Оригінальні дані - з read.csv.
Скотт Гофман

1
Давайте подивимось str()на data.frame.
Роман Луштрик

@ Роман Дякую за функцію str (), я про це не знав. Отже, позбувшись стовпця "Фактор", я можу генерувати такий об’єкт xts, як x <-xts (d [, 3: 5], order.by = d [, 1]). Тоді я зміг звернутися до .hourly, що скорочує дані з об'єктів 19720 року до 480. Я не впевнений, чи отримає це мене куди я хочу, але я зараз ближче, думаю.
Скотт Гофман

Відповіді:


14

Ось один підхід із використанням cut () для створення відповідних годинних факторів та ddply () з бібліотеки plyr для обчислення засобів.

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)))

Дякую за це ... Я думаю, що мені може знадобитися переформулювати це питання, або задати нове. Дивлячись на це запитання stats.stackexchange.com/questions/980/… , я думаю, що отримати засоби - це не саме те, що я прагну.
Скотт Гофман

@JVM Чи можете ви пояснити, як працює функція getmeans, і чому ви не просто використали середні функції або функції colMeans?
Скотт Гофман

1
Функція ddply () розрізає початковий набір даних на підмножини, визначені хостами та годиною. Потім він передає їх до getmeans () як data.frame. Для вашого завдання використання colMeans (), ймовірно, спрацювало б добре, але вам, мабуть, потрібно спочатку видалити стовпці, які вам не потрібні. Приємно в тому, що використовувати ddply () таким чином, що ви можете обчислити будь-яку довільну статистику, для якої ви могли б бути зацікавлені; наприклад, sd (), range () тощо.
Джейсон Морган

6

Агрегація також працює без використання zoo(із випадковими даними з 2 змінних протягом 3 днів та 4 хостів, як від JWM). Я припускаю, що у вас є дані від усіх хостів за кожну годину.

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)

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

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)

Результат виглядає приблизно так:

> 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

Я також не зовсім впевнений у тому, який тип графіка ви хочете. Ось версія графіка з голими кістками лише для першої змінної з окремими рядками даних для кожного хоста.

# 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)

Той самий графік для даних, який є усередненим протягом кожної години.

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)

Гарна відповідь, багато там, з чим я не знайомий, тому мені потрібно спробувати це. Тим не менш, дивлячись на мої дані своїми методами, я думаю, що мені потрібно також показати високі моменти у своїх даних. Спасибі
Скотт Хоффман

2

Ви можете замовити aggregate.zooфункцію з пакета zoo: http://cran.r-project.org/web/packages/zoo/zoo.pdf

Чарлі


Чи можете ви допомогти мені зрозуміти, чому я отримую НС під час роботи?
Скотт Гофман

Привіт Скотт, я фактично не використовував цю aggregate.zooфункцію, хоча zooпакет використовував . Ви переконалися, що ваш об'єкт був zooспочатку об’єктом? Документація, на яку я вказував, повинна вам допомогти там.
Чарлі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.