2012-03-26 28 views
6

tôi có giá trị của một năm của dữ liệu theo giờ trong một khung dữ liệu trong R:tập hợp, tái cấu trúc dữ liệu chuỗi thời gian theo giờ trong R

> str(df.MHwind_load) # compactly displays structure of data frame 
'data.frame': 8760 obs. of 6 variables: 
$ Date   : Factor w/ 365 levels "2010-04-01","2010-04-02",..: 1 1 1 1 1 1 1 1 1 1 ... 
$ Time..HRs. : int 1 2 3 4 5 6 7 8 9 10 ... 
$ Hour.of.Year : int 1 2 3 4 5 6 7 8 9 10 ... 
$ Wind.MW  : int 375 492 483 476 486 512 421 396 456 453 ... 
$ MSEDCL.Demand: int 13293 13140 12806 12891 13113 13802 14186 14104 14117 14462 ... 
$ Net.Load  : int 12918 12648 12323 12415 12627 13290 13765 13708 13661 14009 ... 

Trong khi duy trì cấu trúc theo giờ, tôi muốn biết làm thế nào để giải nén

  1. một tháng/nhóm đặc biệt của tháng
  2. ngày đầu tiên/tuần đầu tiên của mỗi tháng vv
  3. tất cả các ngày thứ Hai, tất cả các ngày thứ Ba vv của năm

Tôi đã thử sử dụng "cắt" không có kết quả và sau khi tìm kiếm trực tuyến, nghĩ rằng "lubridate" có thể làm như vậy nhưng chưa tìm thấy ví dụ phù hợp. Tôi rất muốn đánh giá cao sự giúp đỡ về vấn đề này.

Edit: một mẫu dữ liệu trong khung dữ liệu là dưới đây:

Date Hour.of.Year Wind.MW datetime 
1 2010-04-01 1 375 2010-04-01 00:00:00 
2 2010-04-01 2 492 2010-04-01 01:00:00 
3 2010-04-01 3 483 2010-04-01 02:00:00 
4 2010-04-01 4 476 2010-04-01 03:00:00 
5 2010-04-01 5 486 2010-04-01 04:00:00 
6 2010-04-01 6 512 2010-04-01 05:00:00 
7 2010-04-01 7 421 2010-04-01 06:00:00 
8 2010-04-01 8 396 2010-04-01 07:00:00 
9 2010-04-01 9 456 2010-04-01 08:00:00 
10 2010-04-01 10 453 2010-04-01 09:00:00 
.. .. ... .......... ........ 
8758 2011-03-31 8758 302 2011-03-31 21:00:00 
8759 2011-03-31 8759 378 2011-03-31 22:00:00 
8760 2011-03-31 8760 356 2011-03-31 23:00:00 

EDIT: bổ sung hoạt động theo thời gian tôi muốn thực hiện trên các tập dữ liệu cùng 1. Thực hiện giờ theo giờ trung bình cho tất cả các điểm dữ liệu tức là trung bình của tất cả các giá trị trong giờ đầu tiên của mỗi ngày trong năm. Đầu ra sẽ là "hồ sơ hàng giờ" của cả năm (24 điểm) 2. Thực hiện tương tự cho mỗi tuần và mỗi tháng tức là có được 52 và 12 cấu hình theo giờ tương ứng 3. Làm trung bình theo mùa, ví dụ cho tháng 6 Tháng Chín

+0

Đây hoàn toàn là câu hỏi liên quan đến lập trình R, không có nội dung thống kê. Chúng tôi di chuyển các câu hỏi như vậy sang stackoverflow, vì ở đây chúng tôi có nhiều lập trình viên hơn. – mpiktas

+0

Tôi đề nghị thêm một số dòng dữ liệu của bạn. Khung hình ở đây với dput. Tôi nghĩ chỉ có cột ngày tháng là đủ. – mpiktas

+0

@mpiktas: Tôi đã thêm một mẫu từ khung dữ liệu của mình. lưu ý rằng tôi đã tạo datetime bằng cách sử dụng _timeSequence_ – avg

Trả lời

6

Chuyển đổi ngày thành định dạng mà lubridate hiểu và sau đó sử dụng các hàm month, mday, wday tương ứng.

Giả sử bạn có một data.frame với thời gian lưu trữ trong cột Date, thì câu trả lời cho câu hỏi của bạn sẽ là:

###dummy data.frame 
df <- data.frame(Date=c("2012-01-01","2012-02-15","2012-03-01","2012-04-01"),a=1:4) 
##1. Select rows for particular month 
subset(df,month(Date)==1) 

##2a. Select the first day of each month 
subset(df,mday(Date)==1) 

##2b. Select the first week of each month 
##get the week numbers which have the first day of the month 
wkd <- subset(week(df$Date),mday(df$Date)==1) 
##select the weeks with particular numbers 
subset(df,week(Date) %in% wkd)  

##3. Select all mondays 
subset(df,wday(Date)==1) 
+0

Tất cả các hoạt động trên đã làm việc ngoại trừ # 2b. Tôi nghi ngờ điều này có thể có liên quan đến dữ liệu của tôi, bắt đầu từ ngày 1 tháng 4 năm 2010 và cho đến ngày 31 tháng 3 năm 2011 - 2 năm dương lịch. – avg

+0

Tôi chạy lệnh: wkd <- tập con (tuần (newdf $ datetime), mday (newdf $ datetime) == 1) all.firstweeks.newdf <- tập hợp con (newdf, week (datetime)% in% wkd) "datetime" ở đây là: datetime <- timeSequence (from = "2010-04-01 00:00", to = "2011-03- 31 23:00 ", by =" hour ") đây là đoạn trích xuất: – avg

+0

đầu ra của: 'all.firstweeks.newdf [1: 240,]' Ngày giờ..HRs. Hour.of.Year Wind.MW MSEDCL.Demand 1 2010-04-01 1 1 375 13293 2 2010-04-01 2 2 492 13140 3 2010-04-01 3 3 483 12806 . ... ... .. . ... ... .. . ... ... .. 168 2010-04-07 24 168 77 14447 673 2010-04-29 1 673 397 13468 674 2010-04-29 2 674 495 13426 – avg

6
  1. tắc đầu tiên để một đại diện Date: as.Date(df.MHwind_load$Date)
  2. Sau đó gọi weekdays trên vectơ ngày để có được một yếu tố mới được gắn nhãn với ngày trong tuần
  3. Sau đó, gọi months trên vectơ ngày để có được một yếu tố mới được gắn nhãn với tên của tháng
  4. Tùy chọn tạo biến số years (xem bên dưới).

Bây giờ subset khung dữ liệu bằng cách sử dụng kết hợp có liên quan này. Bước 2. Nhận câu trả lời cho nhiệm vụ của bạn 3. Bước 3. và 4. đưa bạn đến nhiệm vụ 1. Nhiệm vụ 2 có thể yêu cầu một hoặc hai dòng R. Hoặc chỉ chọn các hàng tương ứng với, nói, tất cả các Thứ Hai trong một tháng và gọi số unique hoặc số điện thoại thay đổi của nó duplicated trên kết quả.

Để giúp bạn đi ...

newdf <- df.MHwind_load ## build an augmented data set 
newdf$d <- as.Date(newdf$Date) 
newdf$month <- months(newdf$d) 
newdf$day <- weekdays(newdf$d) 

## for some reason R has no years function. Here's one 
years <- function(x){ format(as.Date(x), format = "%Y") } 

newdf$year <- years(newdf$d) 

# get observations from January to March of every year 
subset(newdf, month %*% in c('January', 'February', 'March')) 

# get all Monday observations 
subset(newdf, day == 'Monday') 

# get all Mondays in 1999 
subset(newdf, day == 'Monday' & year == '1999') 

# slightly fancier: _first_ Monday of each month 
# get the first weeks 
first.week.of.month <- !duplicated(cbind(newdf$month, newdf$day)) 
# now pull out the mondays 
subset(newdf, first.monday.of.month & day=='Monday') 
+0

Cảm ơn khách hàng tiềm năng. Tôi đã có thể sử dụng các chức năng này nhưng đã bị mắc kẹt khi xây dựng mã để phân tích dữ liệu của tôi. Tôi đang cố gắng giải pháp @Bryan Goodrich .. – avg

+0

Thực tế bây giờ tôi đã viết điều này, tôi nghĩ rằng tôi thích điều 'lubridate' tốt hơn một chút trong các câu trả lời khác. Hãy suy nghĩ của mã ở đây như là một giới thiệu về lệnh 'subset' :-) – conjugateprior

3

Vì bạn đang không yêu cầu về thời gian (giờ) một phần của dữ liệu của bạn, cách tốt nhất là sau đó lưu trữ dữ liệu của bạn như là một đối tượng Date. Nếu không, bạn có thể quan tâm đến chron, cũng có một số chức năng tiện lợi như bạn sẽ thấy bên dưới.

Đối với câu trả lời của Conjugate Prior, bạn nên lưu trữ dữ liệu ngày làm đối tượng Ngày. Vì dữ liệu của bạn đã theo định dạng mặc định ('yyyy-mm-dd'), bạn có thể gọi as.Date trên đó. Nếu không, bạn sẽ phải chỉ định định dạng chuỗi của mình. Tôi cũng sẽ sử dụng as.character trên yếu tố của bạn để đảm bảo rằng bạn không nhận được lỗi nội tuyến. Tôi biết tôi đã gặp phải vấn đề với các yếu tố thành Ngày vì lý do đó (có thể đã được sửa trong phiên bản hiện tại).

df.MHwind_load <- transform(df.MHwind_load, Date = as.Date(as.character(Date))) 

Bây giờ bạn sẽ làm tốt để tạo các hàm bao bọc trích xuất thông tin bạn muốn. Bạn có thể sử dụng chuyển đổi như tôi đã làm ở trên để chỉ cần thêm các cột đại diện cho tháng, ngày, năm, v.v ... và sau đó đặt con vào chúng một cách hợp lý. Ngoài ra, bạn có thể làm điều gì đó như thế này:

getMonth <- function(x, mo) { # This function assumes w/in single year vector 
    isMonth <- month(x) %in% mo # Boolean of matching months 
    return(x[which(isMonth)]  # Return vector of matching months 
} # end function 

Hoặc, ở dạng ngắn

getMonth <- function(x, mo) x[month(x) %in% mo] 

Đây chỉ là một sự cân bằng giữa việc lưu trữ thông tin (chuyển đổi khung hình) hoặc có nó xử lý khi mong muốn (sử dụng accessor phương pháp).

Một quá trình phức tạp hơn là nhu cầu của bạn đối với ngày đầu tiên của tháng. Tuy nhiên, điều này không hoàn toàn khó khăn. Dưới đây là một hàm sẽ trả về tất cả các giá trị đó, nhưng nó khá đơn giản để chỉ tập hợp một vector được sắp xếp các giá trị cho một tháng cụ thể và lấy giá trị đầu tiên của chúng.

getFirstDay <- function(x, mo) { 
    isMonth <- months(x) %in% mo 
    x <- sort(x[isMonth]) # Look at only those in the desired month. 
         # Sort them by date. We only want the first day. 
    nFirsts <- rle(as.numeric(x))$len[1] # Returns length of 1st days 
    return(x[seq(nFirsts)]) 
} # end function 

Giải pháp thay thế dễ dàng hơn sẽ

getFirstDayOnly <- function(x, mo) {sort(x[months(x) %in% mo])[1]} 

tôi đã không prototyped này, như bạn đã không cung cấp bất kỳ mẫu dữ liệu, nhưng đây là loại phương pháp có thể giúp bạn có được những thông tin bạn mong muốn. Đó là vào bạn để tìm ra cách để đưa chúng vào dòng chảy công việc của bạn. Ví dụ: giả sử bạn muốn lấy ngày đầu tiên cho mỗi tháng của một năm nhất định (giả sử chúng tôi chỉ xem xét một năm; bạn có thể tạo trình bao bọc hoặc xử lý trước véc tơ của mình cho một năm trước).

# Return a vector of first days for each month 
df <- transform(df, date = as.Date(as.character(date))) 
sapply(unique(months(df$date)), # Iterate through months in Dates 
     function(month) {getFirstDayOnly(df$date, month)}) 

Ở trên cũng có thể được thiết kế như một chức năng tiện lợi riêng biệt sử dụng chức năng truy cập khác. Bằng cách này, bạn tạo ra một loạt các phương pháp trực tiếp nhưng súc tích để nhận được các mẩu thông tin mà bạn muốn. Sau đó, bạn chỉ cần kéo chúng lại với nhau để tạo ra các chức năng diễn giải rất đơn giản và dễ dàng mà bạn có thể sử dụng trong các tập lệnh của mình để giúp bạn chính xác những gì bạn mong muốn theo cách hiệu quả nhất.

Bạn sẽ có thể sử dụng các ví dụ trên để tìm hiểu cách thử nghiệm các trình bao bọc khác để truy cập thông tin ngày bạn yêu cầu. Nếu bạn cần trợ giúp về những người đó, hãy hỏi trong một bình luận.

+0

cảm ơn cho các câu trả lời chi tiết, nó giúp vì tôi không phải là rất thành thạo trong R. tôi đã làm những gì bạn đề nghị với kết quả sau: 'alt. allfirstdays.newdf <- sapply (duy nhất (tháng (datetime)), chức năng (tháng) {getFirstDay (giờ, tháng)}) – avg

+0

Lỗi trong Math.data.frame (miếng [, 1: 5]): không biến số trong khung dữ liệu: tháng "datetime" tại đây là: 'datetime <- timeSequence (from = "2010-04-01 00:00", to = "2011-03-31 23:00", bởi = "hour") ' "tháng" ở đây, hàm trong _lubridate_ hoặc biến mới là gì? Tôi đã thử làm _months (datetime) _ với cùng một kết quả – avg

+0

Cách tiếp cận của tôi làm việc với các đối tượng Date class, không phải lubridate (không bao giờ sử dụng nó trước đây). Điểm của việc sử dụng Date - như trái ngược với, giả sử, _chron _-- là thành phần thời gian không quan trọng. Nếu dữ liệu của bạn là "2010-04-01" thì as.Date ("2010-04-01") lưu trữ dữ liệu chính xác. Nếu thay vào đó bạn đã có "01/04/2010" thì bạn sẽ phải làm như vậy. ("01/04/2010", format = "% d /% m /% Y"). Xem các trang trợ giúp để biết chi tiết. Nếu dữ liệu của bạn bao gồm thời gian, bạn sẽ phải loại bỏ phần đó ra. Trong khi strsplit có thể hoạt động, nó đủ đồng bộ để chỉ làm chuỗi con ("2010-04-01 00:00", 1, 10) và as.Date. –

Các vấn đề liên quan