Làm thế nào để tổng hợp theo dữ liệu phút trong một tuần thành phương tiện hàng giờ?


15

Làm thế nào bạn có thể nhận được phương tiện hàng giờ cho nhiều cột dữ liệu, trong một khoảng thời gian hàng ngày và hiển thị kết quả cho mười hai "Máy chủ" trong cùng một biểu đồ? Đó là, tôi muốn vẽ biểu đồ của một khoảng thời gian 24 giờ, cho dữ liệu trong một tuần. Mục tiêu cuối cùng sẽ là so sánh hai bộ dữ liệu này, trước và sau khi lấy mẫu.

            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

Tôi đã có thể chạy xyplot (CPUUser ~ ngày | Máy chủ) với hiệu quả tốt. Tuy nhiên, thay vì hiển thị mỗi ngày trong tuần, tôi muốn trục X là giờ trong ngày.

Cố gắng đưa dữ liệu này vào một đối tượng xts dẫn đến các lỗi như "order.by yêu cầu một đối tượng dựa trên thời gian thích hợp"

Đây là một str () của khung dữ liệu:

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

CẬP NHẬT: Chỉ để tham khảo trong tương lai, tôi quyết định đi cùng với một boxplot, để hiển thị cả trung vị và 'ngoại lệ'.

Bản chất:

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)

Cảm ơn


Tôi đoán bạn nhận được những lỗi đó xts()datescột là một yếu tố.
Joshua Ulrich

Tôi thực sự mới với R ... Tôi đã tạo cột ngày từ hàm strptime. Dữ liệu gốc là từ read.csv.
Scott Hoffman

1
Chúng ta hãy xem str()data.frame.
Roman Luštrik

@Roman Cảm ơn hàm str (), tôi không biết điều đó. Vì vậy, thoát khỏi cột Factor, tôi có thể tạo một đối tượng xts như thế này, x <-xts (d [, 3: 5], order.by = d [, 1]). Sau đó tôi đã có thể áp dụng cho. Cuối cùng, nó rút ngắn dữ liệu từ 19720 đối tượng xuống còn 480. Tôi không chắc liệu điều này có đưa tôi đến nơi tôi muốn không, nhưng tôi nghĩ gần hơn.
Scott Hoffman

Câu trả lời:


14

Dưới đây là một cách tiếp cận bằng cách sử dụng cut () để tạo các yếu tố hàng giờ và ddply () thích hợp từ thư viện plyr để tính toán phương tiện.

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

Cảm ơn vì điều này ... Tôi nghĩ rằng tôi có thể cần phải đặt lại câu hỏi mặc dù hoặc hỏi một câu hỏi mới. Nhìn vào câu hỏi này stats.stackexchange.com/questions/980/ , bây giờ tôi nghĩ rằng việc có được phương tiện không chính xác là những gì tôi đang theo đuổi.
Scott Hoffman

@JVM Bạn có thể giải thích cách hàm getmeans hoạt động không và tại sao bạn không sử dụng hàm trung bình hoặc hàm colMeans?
Scott Hoffman

1
Hàm ddply () cắt tập dữ liệu gốc thành các tập con được xác định bởi máy chủ và giờ. Sau đó, nó chuyển những thứ này đến getmeans () dưới dạng data.frame. Đối với nhiệm vụ của bạn, sử dụng colMeans () có thể sẽ hoạt động tốt, nhưng trước tiên bạn có thể cần xóa các cột bạn không cần. Điều tuyệt vời khi sử dụng ddply () theo cách này là bạn có thể tính toán bất kỳ chỉ số tùy ý nào mà bạn có thể quan tâm; ví dụ: sd (), phạm vi (), v.v.
Jason Morgan

6

Tập hợp cũng hoạt động mà không cần sử dụng zoo(với dữ liệu ngẫu nhiên từ 2 biến trong 3 ngày và 4 máy chủ như từ JWM). Tôi giả sử rằng bạn có dữ liệu từ tất cả các máy chủ cho mỗi giờ.

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)

Tôi không hoàn toàn chắc chắn nếu bạn muốn trung bình chỉ trong vòng mỗi giờ, hoặc trong mỗi giờ trong tất cả các ngày. Tôi sẽ làm cả hai.

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)

Kết quả trông như thế này:

> 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

Tôi cũng không hoàn toàn chắc chắn về loại biểu đồ bạn muốn. Đây là phiên bản cơ bản của đồ thị cho biến đầu tiên với các dòng dữ liệu riêng biệt cho mỗi máy chủ.

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

Biểu đồ tương tự cho dữ liệu chỉ được tính trung bình trong mỗi giờ.

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)

Phản hồi tốt đẹp, có nhiều trong đó tôi không quen thuộc, vì vậy tôi cần phải thử nó. Tuy nhiên, nhìn vào dữ liệu của tôi bằng các phương pháp của bạn, tôi nghĩ tôi cũng cần thể hiện những điểm cao trong dữ liệu của mình. Cảm ơn
Scott Hoffman

2

Bạn có thể kiểm tra aggregate.zoochức năng từ gói zoo: http://cran.r-project.org/web/packages/zoo/zoo.pdf

Charlie


Bạn có thể giúp tôi hiểu lý do tại sao tôi nhận được NA khi chạy này không?
Scott Hoffman

Xin chào Scott, tôi chưa thực sự sử dụng aggregate.zoochức năng này, mặc dù tôi đã sử dụng zoogói này. Bạn có chắc chắn rằng đối tượng của bạn là một zoođối tượng đầu tiên? Các tài liệu mà tôi chỉ để giúp bạn ở đó.
Charlie
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.