2013-11-22 3 views
3

Большое спасибо за ваш комментарий/ответ.Эффективное манипулирование временными рядами в таблице данных R Таблица

Контекст: У меня есть таблица данных с ежедневными ценами на обменные курсы в десятках стран. Столбцы: [ID, Date, X1Y, X2Y, X3Y ... X30Y], где X..Y - столбцы, указывающие часть кривой доходности (например, X1Y - однолетний своп, X3Y - трехлетний своп). Две клавиши: ID (например, «AUD», «GBP») и Дата (например, «2001-04-13», «2001-04-16»).

фиктивные данные:

set.seed(123) 
dt <- cbind(ID=rep(c("AUD","GBP"),c(100,100)),X1Y=rnorm(200),X2Y=rnorm(200),X3Y=rnorm(200)) 
dt <- data.table(dt) 
dt[,Date := seq(from=as.IDate("2013-01-01"), by="1 day", length.out=100)] 
setkeyv(dt,c("ID","Date")) 

Проблема 1: Сначала сгенерировать фиктивные сигналы. Каков синтаксис, если имеется 100 столбцов с довольно сложной формулой генерации сигнала, закодированной в отдельной функции, например genSig (X1Y)? Вот что я имею в виду используя только 3 колонки и некоторые бессмысленные формулы:

dt[,SIG1 :=c(0, diff(X1Y ,1)),by="ID"] 
dt[,SIG2 :=c(0, diff(X2Y ,1)),by="ID"] 
dt[,SIG3 :=c(0, diff(X3Y ,1)),by="ID"] 

Задача 2: Карри вперед колонка (ы) на основе «середине месяца». Например, используя столбцы SIG, я хотел бы сделать все, после того, как 15-го числа каждого месяца будут такими же, как и сигнал 15-го, до 15-го числа следующего месяца. Трудность в том, что фактические данные содержат только торговые дни, поэтому в течение нескольких месяцев нет 15-го, если это выходные/выходные. Другой проблемой является использование эффективного синтаксиса, я мог бы достичь что-то подобное с помощью цикла (я знаю ..) для начала каждого месяца, чтобы показать, что я имел в виду:

for (i in 2:length(dt$Date)){ 
    if(as.POSIXlt(dt[i,]$Date)$mon == as.POSIXlt(dt[i-1,]$Date)$mon){ 
    dt[i, SIG1 := dt[i-1,SIG1]] 
    dt[i, SIG2 := dt[i-1,SIG2]] 
    dt[i, SIG3 := dt[i-1,SIG3]] 
    } 
} 

Я не могу понять, как бороться с вопросом «среднего месяца», поскольку он может попасть на 15-й или 16-й или 17-й. Как и проблема 1, было бы полезно, если бы был умный способ вставки/обновления нескольких/десятков столбцов.

ответ

1
# problem 1 
nsig <- 3L 
csig <- 1:nsig+1L 
newcols <- paste('SIG',1:nsig,sep='') 
dt[,(newcols):=0] 
for (j in csig) set(dt,j=j+nsig+1L,value=c(0, diff(dt[[j]],1))) 

Посмотрев на @ EDDI отвечают, я вижу, что set не очень полезно для задачи 2. Вот что я хотел бы сделать:

dt[,(newcols):=lapply(newcols,function(x) get(x)[1]),by=list(ID,month(Date-14))] 

Согласно this answer, вы можете вычесть дней с даты в этом случае.


Рядом. Передвижные векторы образуют матрицу. В вашем примере у вас есть матрица символов. Я думаю, что вы искали ...

# Creating better data... 
set.seed(123) 
dt <- data.table(ID=rep(c("AUD","GBP"),c(100,100)), 
    X1Y=rnorm(200),X2Y=rnorm(200),X3Y=rnorm(200), 
    Date=seq(from=as.IDate("2013-01-01"), by="1 day", length.out=100)) 
+1

Thanks Frank. Это помогает! – rquant

2

Насколько проблема 2 идет, вы можете использовать прокатный присоединяется:

# small sample to demonstrate 
dt = data.table(date = as.Date(c('2013-01-01', '2013-01-15', '2013-01-17', '2013-02-14', '2013-02-17'), '%Y-%m-%d'), val = 1:5) 
dt 
#   date val 
#1: 2013-01-01 1 
#2: 2013-01-15 2 
#3: 2013-01-17 3 
#4: 2013-02-14 4 
#5: 2013-02-17 5 

setkey(dt, date) 
midmonth = seq(as.Date('2013-01-15', '%Y-%m-%d'), 
       as.Date('2013-12-15', '%Y-%m-%d'), 
       by = '1 month') 

dt[, flag := 0] 
dt[J(midmonth), flag := 1, roll = -Inf] 
dt 
#   date val flag 
#1: 2013-01-01 1 0 
#2: 2013-01-15 2 1 
#3: 2013-01-17 3 0 
#4: 2013-02-14 4 0 
#5: 2013-02-17 5 1 

И теперь вы можете cumsum в flag получить группировку вы хотите например do:

dt[, val1 := val[1], by = cumsum(flag)] 
dt 
#   date val flag val1 
#1: 2013-01-01 1 0 1 
#2: 2013-01-15 2 1 2 
#3: 2013-01-17 3 0 2 
#4: 2013-02-14 4 0 2 
#5: 2013-02-17 5 1 5 
Смежные вопросы