基于多个行和列条件在数据表上操作

时间:2017-05-05 04:12:15

标签: r data.table subset

说我有以下数据表:

prc = c(2,5,4,6,7,3)
ret = c(0.01,0.03,-0.02,0.01,-0.001,0.04)
cap = c(100,200,300,80,40,900)
comp = c("a","a","a","b","b","c")
dt = data.table(comp, prc, ret, cap)

   comp prc    ret cap
1:    a   2  0.010 100
2:    a   5  0.030 200
3:    a   4 -0.020 300
4:    b   6  0.010  80
5:    b   7 -0.001  40
6:    c   3  0.040 900

我想基于以下条件进行操作:对于每个公司,在第t行,必须在行(t-2)处有一个prc,在行(t-1)处有一个prc,并且在(t- 2)。因此,我将操作的唯一行是3.

我试过这个:

> dt[, which(is.na(shift(prc,2)) | is.na(shift(ret,1)) | is.na(shift(v,2))), by = comp]
   comp V1
1:    a  1
2:    a  2
3:    b  1
4:    b  2
5:    c  1

正如预期的那样,唯一不包括的行是comp = a和prc = 4的行。现在我该怎么做才能对该行进行数学运算。请注意,我不想删除其余行,因为它们将用于计算所需行。

2 个答案:

答案 0 :(得分:1)

可能有帮助

dt[dt[, .I[seq_len(.N)>=3], comp]$V1]
#   comp prc   ret cap
#1:    a   4 -0.02 300

如果目的不是为了子集,而是为了新列,请说“标记”显示TRUE / FALSE值

dt[,  Flag := seq_len(.N)>=3, comp]

答案 1 :(得分:0)

OP已经走上了正轨,但已经中途停止了。

dt[, which(is.na(shift(prc, 2)) | is.na(shift(ret, 1)) | is.na(shift(cap, 2))), by = comp]
#   comp V1
#1:    a  1
#2:    a  2
#3:    b  1
#4:    b  2
#5:    c  1

选择每个组中满足要求的所有行。 (注意,在原始代码中,OP引用了v,它不存在于数据集中)。

否定,

dt[, which(!(is.na(shift(prc, 2)) | is.na(shift(ret, 1)) | is.na(shift(cap, 2)))), by = comp]
#   comp V1
#1:    a  3

选择满足要求的每个组中的所有行。

dt[, .SD[!is.na(shift(prc, 2)) & !is.na(shift(ret, 1)) & !is.na(shift(cap, 2))], by = comp]
#   comp prc   ret cap
#1:    a   4 -0.02 300

返回原始data.table的所有行,它们满足包括所有列的条件。

请注意:(a)布尔代数已用于将条件!(A | B | C)替换为!A & !B & !C,并且(b)对which()的调用已被视为多余。

The solution of akrun可以通过类似方式简化。而不是

dt[dt[, .I[seq_len(.N)>=3], comp]$V1]

我们可以写

dt[, .SD[seq_len(.N) >= 3L], comp]

请注意,两种方法 完全等效。虽然后一种方法只是显示每个comp的所有行,这些行至少有两行,但第一种方法还检查NA的内容,我认为这些内容更可靠。