如何将data.table转换为具有唯一日期的行,并将其他行(具有重复日期)转换为列

时间:2015-10-21 11:42:00

标签: r data.table dplyr

不确定我的头衔是否合适。假设我保存了这样的数据。表:

set.seed(1234);
Type <- c("o", "o", "o", "o", "o", "o", "o", "s", "s", "s", "s", "s");
Contract.Month <- c("F", "G", "F", "G", "F", "G", "H", "F", "G", "F", "G", "F");
Date <- c(as.Date("2015-10-21"), as.Date("2015-10-21"), as.Date("2015-10-22"), as.Date("2015-10-22"), as.Date("2015-10-23"), as.Date("2015-10-23"), as.Date("2015-10-23"),  as.Date("2015-10-21"),  as.Date("2015-10-21"),  as.Date("2015-10-22"),  as.Date("2015-10-22"),  as.Date("2015-10-23"));
Price <- rnorm(12);
Volume <- c(11, 10, 0, 12, 0, 0, 12, 1, 1, 1, 1, 1);
DT = data.table(Date, Price, Type, Contract.Month, Volume);

这样的表结果如下:

     Date      Price      Type     Contract.Month Volume
 1: 2015-10-21 -1.2070657    o              F     11
 2: 2015-10-21  0.2774292    o              G     10
 3: 2015-10-22  1.0844412    o              F      0
 4: 2015-10-22 -2.3456977    o              G     12
 5: 2015-10-23  0.4291247    o              F      0
 6: 2015-10-23  0.5060559    o              G      0
 7: 2015-10-23 -0.5747400    o              H     12
 8: 2015-10-21 -0.5466319    s              F      1
 9: 2015-10-21 -0.5644520    s              G      1
10: 2015-10-22 -0.8900378    s              F      1
11: 2015-10-22 -0.4771927    s              G      1
12: 2015-10-23 -0.9983864    s              F      1

现在我想要实现的是获取具有类型“o”的唯一日期的所有行,并将具有类型“s”的行转换为列。结果将是这样的:

 Date      Price      Contract.Month Volume  S1.Price     S2.Price
 1: 2015-10-21 -0.7485253        F     11    -0.5466319 -0.5644520
 2: 2015-10-22  0.3015246        G     12    -0.4771927
 3: 2015-10-23  0.4846456        H     12

为了解释一下,我在实际情况中所拥有的是期货价格和它们的价差加载在一个大数据中。 “o”是完全的,“s”是传播的。所以我想从直接行创建连续合同,然后将该月的所有点差添加到当天作为列。因此,在我的示例中,我使用volume来创建连续合同(如果volume为0,那么当天不使用该合同,但我也想简单地使用最早的合同并将其用作到期时另一种方法)。 在我的例子中,第一天有两个点差 - 因为直接是F而点差是F和G.第二天只有G点差,因为直接已经是G.而且第三天没有点差信息,因为直接合约月份比传播点差一天。

我已经尝试了几天但是没有成功。我是R和数据表的新手,但基本原理对我来说似乎很清楚,我只是不知道如何实现这种精确的转换,因为它看起来并不简单。任何帮助将不胜感激!

修改已添加set.seed

EDIT2 如果有人发现了这个问题我做了类似的事情(抱歉没有检查它是否适用于样本数据,但你可以得到一个想法):

DTs <- DT %>% filter(Type=="s")
DTo <- DT %>% filter(Type=="o")
DT1 <- DT %>% filter(Type=="o") %>% group_by(Date) %>% filter(Date == Date & Contract.Month == min(Contract.Month) & Volume != 0)
out = inner_join(DT1, DTs, by = c("Date" = "Date")) %>% filter(Contract.Month.x <= Contract.Month.y)
out = out[, s1_seq:=paste0('s1_', seq(.N)), by=Date]
dcast(out, ... ~ s1_seq, value.var = c("Contract.Month.y", "Price.y"))

1 个答案:

答案 0 :(得分:1)

我尝试了一下这就是我要做的:(我使用set.seed(1234),你需要库(dplyr)来执行代码)

$('#button').on('click', function (e) {

    //some logic
    $(this).css('color', 'red');

    return false;
});

第一部分很简单,DT1包含来自小组的唯一天数&#34; o&#34;按最大音量过滤:

DT1 <- DT %>% filter(Type=="o") %>% group_by(Date) %>% filter(Volume==max(Volume))

第二部分有点棘手,我使用的代码运行时间不好,但这是我提出的解决方案:

        Date     Price Type Contract.Month Volume
1 2015-10-21 -1.207066    o              F     11
2 2015-10-22 -2.345698    o              G     12
3 2015-10-23 -0.574740    o              H     12

创建虚拟子集和包含所有可能合约月份的新数据框。

DTs <- DT %>% filter(Type=="s")
DTo <- DT %>% filter(Type=="o")

out <- data.frame(matrix(NA,ncol=length(unique(DT$Contract.Month)),nrow=length(unique(DTo$Date))),"Date"=unique(DTo$Date))
names(out) <- c(unique(DT$Contract.Month),"Date")

现在每个可能的合约月份在两个虚拟数据集中按天进行比较,如果来自类型o!= 0的交易量,则类型s的价格将保存在特定合约月份中。

for(i in 1:nrow(out)){
  for(j in 1:length(unique(DT$Contract.Month))){

    if((nrow(DTo[which(DTo$Contract.Month==names(out)[j]&DTo$Date==out[i,"Date"])])!=0) & 
       (nrow(DTs[which(DTs$Contract.Month==names(out)[j]&DTs$Date==out[i,"Date"])])!=0)){
         out[i,j] <- ifelse(DTo[which(DTo$Contract.Month==names(out)[j]&DTo$Date==out[i,"Date"])] %>% select(Volume) == 0,NA,DTs[which(DTs$Contract.Month==names(out)[j]&DTs$Date==out[i,"Date"])] %>% select(Price))
     }
  }
}

绑定此数据框架,结果看起来就像您从我的问题中得到的内容。

希望这对你有所帮助。