Hãy lấy dữ liệu sau:R: sử dụng data.table: = hoạt động để tính toán các cột mới
dt <- data.table(TICKER=c(rep("ABC",10),"DEF"),
PERIOD=c(rep(as.Date("2010-12-31"),10),as.Date("2011-12-31")),
DATE=as.Date(c("2010-01-05","2010-01-07","2010-01-08","2010-01-09","2010-01-10","2010-01-11","2010-01-13","2010-04-01","2010-04-02","2010-08-03","2011-02-05")),
ID=c(1,2,1,3,1,2,1,1,2,2,1),VALUE=c(1.5,1.3,1.4,1.6,1.4,1.2,1.5,1.7,1.8,1.7,2.3))
setkey(dt,TICKER,PERIOD,ID,DATE)
Bây giờ cho từng tổ hợp ticker/thời gian, tôi cần những điều sau đây trong một cột mới:
PRIORAVG
: Giá trị trung bình của VALUE mới nhất của từng ID, không bao gồm ID hiện tại, cung cấp ID không quá 180 ngày.PREV
: Giá trị trước đó từ cùng một ID.
Kết quả sẽ giống như thế này:
TICKER PERIOD DATE ID VALUE PRIORAVG PREV
[1,] ABC 2010-12-31 2010-01-05 1 1.5 NA NA
[2,] ABC 2010-12-31 2010-01-08 1 1.4 1.30 1.5
[3,] ABC 2010-12-31 2010-01-10 1 1.4 1.45 1.4
[4,] ABC 2010-12-31 2010-01-13 1 1.5 1.40 1.4
[5,] ABC 2010-12-31 2010-04-01 1 1.7 1.40 1.5
[6,] ABC 2010-12-31 2010-01-07 2 1.3 1.50 NA
[7,] ABC 2010-12-31 2010-01-11 2 1.2 1.50 1.3
[8,] ABC 2010-12-31 2010-04-02 2 1.8 1.65 1.2
[9,] ABC 2010-12-31 2010-08-03 2 1.7 1.70 1.8
[10,] ABC 2010-12-31 2010-01-09 3 1.6 1.35 NA
[11,] DEF 2011-12-31 2011-02-05 1 2.3 NA NA
Lưu ý PRIORAVG
trên hàng 9 là tương đương với 1,7 (tương đương với các VALUE
trên hàng 5, đó là quan sát trước chỉ trong quá khứ 180 ngày khác ID
)
Tôi đã phát hiện gói data.table
, nhưng tôi dường như không thể hiểu đầy đủ chức năng :=
. Khi tôi giữ nó đơn giản, nó có vẻ hoạt động. Để có được giá trị trước đó cho mỗi ID (tôi dựa trên giải pháp cho this question):
dt[,PREV:=dt[J(TICKER,PERIOD,ID,DATE-1),roll=TRUE,mult="last"][,VALUE]]
này hoạt động tuyệt vời, và nó chỉ mất 0,13 giây để thực hiện thao tác này trên bộ dữ liệu của tôi với ~ hàng 250k; chức năng quét véc-tơ của tôi có kết quả giống nhau nhưng chậm hơn khoảng 30.000 lần.
Ok, vì vậy tôi đã có yêu cầu đầu tiên của mình. Hãy đến yêu cầu thứ hai, phức tạp hơn. Ngay bây giờ, phương pháp nhịn ăn cho đến nay đối với tôi là sử dụng một vài lần quét vectơ và ném hàm thông qua hàm plyr
adply
để nhận kết quả cho mỗi hàng.
calc <- function(df,ticker,period,id,date) {
df <- df[df$TICKER == ticker & df$PERIOD == period
& df$ID != id & df$DATE < date & df$DATE > date-180, ]
df <- df[order(df$DATE),]
mean(df[!duplicated(df$ID, fromLast = TRUE),"VALUE"])
}
df <- data.frame(dt)
adply(df,1,function(x) calc(df,x$TICKER,x$PERIOD,x$ID,x$DATE))
tôi đã viết hàm cho một data.frame
và nó dường như không làm việc với một data.table
. Đối với một tập hợp con của 5000 hàng, điều này mất khoảng 44 giây nhưng dữ liệu của tôi bao gồm> 1 triệu hàng. Tôi tự hỏi nếu điều này có thể được thực hiện hiệu quả hơn thông qua việc sử dụng :=
.
dt[J("ABC"),last(VALUE),by=ID][,mean(V1)]
Điều này hoạt động để chọn mức trung bình của VALUE mới nhất cho mỗi ID cho ABC.
dt[,PRIORAVG:=dt[J(TICKER,PERIOD),last(VALUE),by=ID][,mean(V1)]]
Tuy nhiên, điều này không tính trung bình của tất cả VALUE cuối cùng cho tất cả các dấu tick/dấu chấm thay vì chỉ cho dấu tick/chu kỳ hiện tại. Vì vậy, nó kết thúc với tất cả các hàng nhận được cùng một giá trị trung bình. Tôi có làm điều gì sai hay đây là giới hạn của :=
?
Gợi ý: tham gia phạm vi được kế thừa cho quan sát hiện hành với 180 ngày qua (sử dụng tiền tố 'i.':' [, j = list (..., age = PERIOD-i.PERIOD, ...),] [age <180] ', và' mult = "last" 'chứ không phải' last() ', có thể. –
Bảng dữ liệu được đề cập có vẻ khác biệt với mã trích xuất ở trên nó. Và nó thiếu') ' dường như. –
đã thêm dữ liệu hiển thị kết quả mong đợi của yêu cầu 180 ngày – Dirk