Быстрое объединение логических матриц с помощью & в R - PullRequest
0 голосов
/ 04 мая 2020

У меня большая логическая матрица, и мне нужно объединить каждый столбец с вектором с помощью операции &. Прямо сейчас я перебираю столбцы в цикле, но это занимает некоторое время, так как строк больше 1 миллиона. Есть ли более быстрый, возможно векторизованный способ сделать это?

mx <- replicate(10, sample(c(T,F), size = 1000, replace = T)) # 1000 rows x 10 columns
bool <- sample(c(T,F), size = 1000, replace = T) # 1000 elements

out <- apply(mx1, 2, function(x) {
  x & bool
})

Для контекста, эти данные взяты из матрицы экспрессии генов, где 1 строка = 1 ячейка

Ответы [ 3 ]

3 голосов
/ 04 мая 2020

Я думаю, вы хотите получить в результате тусклость mx, в которой каждая строка & имеет соответствующее единственное значение bool. Я думаю, у вас все в порядке, ничего не делая извне.

set.seed(42)
mx <- replicate(4, sample(c(T,F), size = 10, replace = T)) # 1000 rows x 10 columns
bool <- sample(c(T,F), size = 10, replace = T) # 1000 elements
cbind(mx, NA, bool)
#                                   bool
#  [1,] FALSE  TRUE FALSE FALSE NA  TRUE
#  [2,] FALSE FALSE  TRUE FALSE NA  TRUE
#  [3,]  TRUE FALSE FALSE  TRUE NA  TRUE
#  [4,] FALSE  TRUE FALSE FALSE NA FALSE
#  [5,] FALSE  TRUE  TRUE  TRUE NA  TRUE
#  [6,] FALSE FALSE FALSE FALSE NA FALSE
#  [7,] FALSE FALSE  TRUE  TRUE NA FALSE
#  [8,]  TRUE  TRUE FALSE  TRUE NA FALSE
#  [9,] FALSE  TRUE  TRUE FALSE NA FALSE
# [10,] FALSE FALSE FALSE FALSE NA FALSE

(Показаны данные cbind ed только для выравнивания значений bool с каждой строкой mx.)

При этом любая строка с bool false должна приводить ко всем FALSE:

mx & bool
#        [,1]  [,2]  [,3]  [,4]
#  [1,] FALSE  TRUE FALSE FALSE
#  [2,] FALSE FALSE  TRUE FALSE
#  [3,]  TRUE FALSE FALSE  TRUE
#  [4,] FALSE FALSE FALSE FALSE
#  [5,] FALSE  TRUE  TRUE  TRUE
#  [6,] FALSE FALSE FALSE FALSE
#  [7,] FALSE FALSE FALSE FALSE
#  [8,] FALSE FALSE FALSE FALSE
#  [9,] FALSE FALSE FALSE FALSE
# [10,] FALSE FALSE FALSE FALSE

Проверка:

out <- apply(mx, 2, function(x) x & bool)
identical(out, mx & bool)
# [1] TRUE
microbenchmark::microbenchmark(apply(mx, 2, function(x) x & bool), mx & bool)
# Unit: nanoseconds
#                                expr   min    lq  mean median    uq     max neval
#  apply(mx, 2, function(x) x & bool) 31100 32400 53029  34400 39750 1644700   100
#                           mx & bool   400   600   824    700   900    3200   100

Использование вашей большей матрицы:

mx <- replicate(10, sample(c(T,F), size = 1000, replace = T)) # 1000 rows x 10 columns
bool <- sample(c(T,F), size = 1000, replace = T) # 1000 elements
dim(mx)
# [1] 1000   10
length(bool)
# [1] 1000

microbenchmark::microbenchmark(apply(mx, 2, function(x) x & bool), mx & bool)
# Unit: microseconds
#                                expr   min     lq    mean median     uq    max neval
#  apply(mx, 2, function(x) x & bool) 336.1 489.70 621.647 605.25 696.05 1999.9   100
#                           mx & bool  65.0  94.25 135.260 129.20 159.50  385.4   100
1 голос
/ 04 мая 2020

В этом случае просто:

mx & bool

bool перерабатывается для всех столбцов в mx

identical(mx & bool, out)

вывод:

[1] TRUE
0 голосов
/ 04 мая 2020

Вы можете попробовать использовать пакет data.table:

n <- 1000000
mx <- replicate(10, sample(c(T,F), size = n, replace = T)) # n rows x 10 columns
bool <- sample(c(T,F), size = n, replace = T) # n elements

# original solution
system.time(
  out <- apply(mx, 2, function(x) {
    x & bool
  })
)

# user  system elapsed 
# 0.20    0.02    0.22 


# using data.table, approx. half the time
dt <- data.table(mx)

system.time(
  out2 <- dt[, lapply(.SD, function(x){x & bool})]
)

# user  system elapsed 
# 0.11    0.00    0.11 
...