R data.table сумма количества столбцов, превышающих порог - PullRequest
0 голосов
/ 01 марта 2019

Я хотел бы суммировать количество столбцов, значения которых превышают порог в наблюдении.Кроме того, я хотел бы указать эти имена столбцов и пороги в качестве векторов (cols, th)

. Взять пример набора данных:

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 и th всегда будут одинаковой длины)

Ответы [ 3 ]

0 голосов
/ 05 марта 2019

@ Подход 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
0 голосов
/ 07 марта 2019

Вот один из способов обойти итерацию по строкам:

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
0 голосов
/ 01 марта 2019

Я думаю, что есть более простой способ решения вашей проблемы:

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]
...