R data.table列总和超过阈值

时间:2019-03-01 19:32:08

标签: r data.table vectorization threshold

我想对观察中值超过阈值的列数求和。另外,我想将这些列名和阈值指定为向量(colsth

以示例数据集为例:

x <- data.table(x1=c(1,2,3),x2=c(3,2,1))

目标是创建一个新列exceed.count,其中x1和x2超过各自阈值的列数。假设x1和x2的阈值均为2:

th <- c(2,2)

该功能可以定义为:

fn <- function(z,th) (sum(z[,x1]>th[1],z[,x2]>th[2]))

列数超过了由以下公式计算得出的阈值:

x[,exceed.count:=fn(.SD,th),by=seq_len(nrow(x))]

结果是:

   x1 x2 exceed.count
1:  1  3            1
2:  2  2            0
3:  3  1            1

我想做的是能够将列名指定为向量,例如

cols <- c("x1","x2")

我正在玩一种形式的函数:

fn.i <- function(z,i) (sum(z[,cols[i],with=FALSE] > th[i]))

它适用于单个i,但是如何在cols元素之间向量化它? (colsth的长度始终相同)

3 个答案:

答案 0 :(得分:1)

我认为有一种更简单的方法可以解决您的问题:

x<-data.table(x1=c(1,2,3),x2=c(3,2,1))
th<-c(2,2)
x[,exceed.count:=sum(.SD>th),by=seq_len(nrow(x))]

或者,考虑到您的输入(仅列的一部分):

x<-data.table(x1=c(1,2,3),x2=c(3,2,1))
sd.cols = c("x1")
th<-c(2)
x[,exceed.count:=sum(.SD>th),by=seq_len(nrow(x)), .SDcols=sd.cols]

x<-data.table(x1=c(1,2,3),x2=c(3,2,1))
sd.cols = c("x1")
th<-c(2,2)
x[,exceed.count:=sum(.SD>th[1]),by=seq_len(nrow(x)), .SDcols=sd.cols]

答案 1 :(得分:1)

@JonnyCrunch的方法,用.SDcols=sd.cols指定列的子集可以很好地工作(只要您确保ncol(x) == length(th),否则向量循环会弄乱事情)。

这是一种语法较短的替代方法(但对于很宽的列,其性能较差):

  • x[,exceed.count:=sum(.SD>th), by=seq_len(nrow(x)) ]
    • 无需显式指定.SDcols,将其默认为所有列
    • 在所有不想计算的列中使用无关值th,为所有列定义阈值向量+Inf

> x <- data.table(x0=4:6, x1=1:3, x2=3:1, x3=7:5)

   x0 x1 x2 x3
1:  4  1  3  7
2:  5  2  2  6
3:  6  3  1  5

> th <- c(+Inf, 2, +Inf, 2) 

> fn <- function(z,th) (z>th)

> x[,exceed.count:=sum(.SD>th), by=seq_len(nrow(x)) ]

   x0 x1 x2 x3 exceed.count
1:  4  1  3  7            1
2:  5  2  2  6            1
3:  6  3  1  5            2

答案 2 :(得分:0)

这是绕过行迭代的一种方法:

x <- data.table(x1=c(1,2,3), x2=c(3,2,1))
thL <- list(x1 = 2, x2 = 2)

nm = names(thL)
x[, n := 0L]
for (i in seq_along(thL)) x[thL[i], on=sprintf("%s>%s", nm[i], nm[i]), n := n + 1L][]

   x1 x2 n
1:  1  3 1
2:  2  2 0
3:  3  1 1