数据准备问题

时间:2013-08-21 08:11:13

标签: r data.table

抱歉非特定的标题。这是感兴趣的data.table:

dt <- data.table(K=c("A","A","A","B","B","B"),Y=c("2010","2010","2011","2011","2011","2010"),Q1=c(2,3,4,1,3,4),Q2=c(3,3,3,1,1,1))
dt
   K    Y Q1 Q2
1: A 2010  2  3
2: A 2010  3  3
3: A 2011  4  3
4: B 2011  1  1
5: B 2011  3  1
6: B 2010  4  1

假设K的值是人,所以我们在这里有两个。一年中的季度存储在Q1和Q2中。 Q2是一种参考四分之一变量,值总是与2011年相关)。现在我想在dt中选择那些行,其中,对于K中的每个Person,Q1位于Q2值之前的4个季度的间隔中。

一个例子:
人员A在Q2中的值为3,因此应选择值2(2011),1(2011),4(2010)和3(2010)。考虑到这个数据集,这只是第2行。第3行中的值Q1 = 4太大,第1行中的值Q1 = 2太小。对于第二个人“B”,仅选择第6行。不是第4行,因为这是与Q2相同的季度(我只想要那些小于Q2中的值,而第5行显然大于Q2中的值。

dt_new
   K    Y Q1 Q2
1: A 2010  3  3
2: B 2010  4  1

总结
 Q2中的值为4意味着:选择Q1中的所有值小于4,其中Y = 2011,并选择Q1中的所有值等于或大于4(所以只有4),其中Y = 2010。结果:3(2011),2(2011),1(2011),4(2010)。此规则适用于Q2的所有值。所有这一切都应该为每个人完成。

我希望我的问题得到解决。我认为有很多方法可以解决这个问题,但是因为我还在学习data.table,所以我想问你一些漂亮而优雅的解决方案(希望有没有)。

谢谢

修改
几乎找到了一个解决方案:这给了我一个逻辑向量。如何提取数据集中的行?

setkey(dt,K)
dt[,(Q1<Q2 & Y=="2011")|(Q1>=Q2 & Y=="2010"),by="K"]
   K    V1
1: A FALSE
2: A  TRUE
3: A FALSE
4: B FALSE
5: B FALSE
6: B  TRUE

不这样做:

log <-dt[,(Q1<Q2 & Y=="2011")|(Q1>=Q2 & Y=="2010"),by="K"]$V1
dt[log]

1 个答案:

答案 0 :(得分:4)

这是一个vanilla行式过滤,因此您不需要(或不应该)使用分组(by = "K"),只需这样做:

dt[(Q1 < Q2 & Y == "2011") | (Q1 >= Q2 & Y == "2010"), ]

或者如果你打算使用4个季度以外的范围,可能会更灵活一些:

quarter.diff <- function(Q1, Y1, Q2, Y2) {
  4L * (as.integer(Y2) - as.integer(Y1)) +
       (as.integer(Q2) - as.integer(Q1))
}

dt[quarter.diff(Q1, Y, Q2, Y2 = "2011")  > 0L &
   quarter.diff(Q1, Y, Q2, Y2 = "2011") <= 4L, ]

这不仅更通用,它读得更好,并使 reference-year-is-2011 假设明确。

请注意我谨慎地将所有列转换为quarter.diff函数内的整数。理想情况下,您的年份和季度数据已经存储为整数而不是字符或数字。

最后,如果您担心quarter.diff被调用两次并且速度是一个问题,您可以暂时将结果存储为评论中建议的@Arun:

dt[{qdiff <- quarter.diff(Q1, Y, Q2, Y2 = "2011")
    qdiff > 0L & qdiff <= 4L}, ]