จะรวมข้อมูลนาทีเป็นเวลาหนึ่งสัปดาห์เป็นรายชั่วโมงได้อย่างไร


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:

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

UPDATE: สำหรับการอ้างอิงในอนาคตฉันตัดสินใจใช้ boxplot เพื่อแสดงค่ามัธยฐานและ 'ค่าผิดปกติ'

เป็นหลัก:

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คอลัมน์เป็นปัจจัย
Joshua Ulrich

ฉันใหม่สำหรับ R ... ฉันสร้างคอลัมน์วันที่จากฟังก์ชั่น strptime ข้อมูลต้นฉบับมาจาก read.csv
Scott Hoffman

1
เรามาดูstr()ข้อมูล data.frame
Roman Luštrik

@ Roman ขอบคุณสำหรับฟังก์ชั่น str () ฉันไม่ทราบว่า ดังนั้นการกำจัดคอลัมน์ Factor ฉันสามารถสร้างวัตถุ xts เช่นนี้ได้ x <-xts (d [, 3: 5], order.by = d [, 1]) จากนั้นฉันก็สามารถนำไปใช้กับได้ซึ่งทำให้ข้อมูลจาก 19720 วัตถุสั้นลงเหลือ 480 ฉันไม่แน่ใจว่าจะให้ฉันได้ที่ที่ฉันต้องการ แต่ตอนนี้ฉันใกล้เข้ามาแล้ว
Scott Hoffman

คำตอบ:


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/…ตอนนี้ฉันคิดว่าการหาค่าเฉลี่ยไม่ใช่สิ่งที่ฉันต้องการ
Scott Hoffman

@JVM คุณสามารถอธิบายว่าฟังก์ชั่น getmeans ทำงานอย่างไรและทำไมคุณไม่เพียงแค่ใช้ฟังก์ชั่น Mean หรือ colMeans?
Scott Hoffman

1
ฟังก์ชัน ddply () ตัดชุดข้อมูลดั้งเดิมเป็นชุดย่อยที่กำหนดโดยโฮสต์และชั่วโมง จากนั้นจะส่งผ่านเหล่านี้ไปยัง getmeans () เป็น data.frame สำหรับงานของคุณการใช้ colMeans () อาจใช้ได้ดี แต่คุณอาจต้องลบคอลัมน์ที่คุณไม่ต้องการก่อน สิ่งที่ดีเกี่ยวกับการใช้ ddply () ด้วยวิธีนี้คือคุณสามารถคำนวณสถิติใด ๆ ที่คุณอาจสนใจ เช่น sd (), range () ฯลฯ
Jason Morgan

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)

การตอบสนองที่ดีมีอยู่มากมายที่ฉันไม่คุ้นเคยดังนั้นฉันต้องลองดู ถึงกระนั้นการดูข้อมูลของฉันด้วยวิธีการของคุณฉันคิดว่าฉันต้องแสดงจุดสูงสุดในข้อมูลของฉันด้วย ขอบคุณ
Scott Hoffman

2

คุณอาจเช็คเอาต์aggregate.zooฟังก์ชั่นจากแพ็คเกจzoo: http://cran.r-project.org/web/packages/zoo/zoo.pdf

ชาร์ลี


คุณช่วยฉันเข้าใจไหมว่าทำไมฉันถึงได้รับ NA เมื่อใช้งานมัน
Scott Hoffman

สวัสดีสกอตต์ฉันไม่ได้ใช้aggregate.zooฟังก์ชั่นจริงแต่ฉันได้ใช้zooแพ็คเกจ คุณแน่ใจหรือไม่ว่าวัตถุของคุณเป็นzooวัตถุแรก? เอกสารที่ฉันชี้ไปจะช่วยคุณได้
Charlie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.