2014-12-18 4 views
0

У меня есть матрица в следующем формате:Найти Max Color & Count

 [,1]  [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] "blue" "red" "blue" "blue" "blue" "red" "green" "blue" "blue" 
[2,] "green" "red" "blue" "blue" "blue" "red" "green" "blue" "blue" 
[3,] "yellow" "red" "blue" "blue" "blue" "red" "green" "blue" "blue" 
[4,] "red" "red" "blue" "blue" "blue" "red" "green" "blue" "blue" 
[5,] "blue" "red" "green" "blue" "blue" "red" "green" "blue" "blue" 
[6,] "green" "red" "green" "blue" "blue" "red" "green" "blue" "blue" 
... 

Как быстро рассчитать максимальный цвет и рассчитывать на ряд.

Например, для строки 1 это будет «синий, 6». Я делаю это с помощью команды apply, которая вызывает «table».

Однако моя матрица имеет 1,9 миллиона строк, поэтому требуется слишком много времени. Как я могу векторизовать это?

+1

Можете ли вы показать код, который вы в настоящее время используется в качестве сравнения? –

+2

Сколько времени стоит «слишком долго»? Как быстро вам это нужно? Если вы не можете ответить на это, то я не думаю, что вы можете сказать, как долго «слишком долго». – Spacedman

+0

Несмотря на то, что кто-то отправил решение, которое ускорило ситуацию, - код, используемый для запуска через 40 секунд или около того. Решение занимает около секунды, что идеально :-). – user1357015

ответ

4

Сколько различных возможностей у вас есть для каждой ячейки матрицы? Это как в вашем примере? Если да что-то вроде следующего может быть быстрее

dat <- structure(c("blue", "green", "yellow", "red", "blue", "green", 
    "red", "red", "red", "red", "red", "red", "red", "red", "blue", 
    "blue", "blue", "blue", "green", "green", "red", "blue", "blue", 
    "blue", "blue", "blue", "blue", "red", "blue", "blue", "blue", 
    "blue", "blue", "blue", "blue", "red", "red", "red", "red", "red", 
    "red", "blue", "green", "green", "green", "green", "green", "green", 
    "blue", "blue", "blue", "blue", "blue", "blue", "blue", "blue", 
    "blue", "blue", "blue", "blue", "blue", "blue", "green"), .Dim = c(7L, 
    9L)) 

values <- c("blue", "red", "green", "yellow") 
counts <- vapply(values, function(value) rowSums(dat == value), 
    numeric(nrow(dat))) # Thanks to @RichardScriven for the improvement :) 
counts 
#  blue red green yellow 
# [1,] 6 2  1  0 
# [2,] 5 2  2  0 
# [3,] 5 2  1  1 
# [4,] 5 3  1  0 
# [5,] 5 2  2  0 
# [6,] 4 2  3  0 
# [7,] 4 4  1  0 

max.value.col <- max.col(counts) 
max.value <- colnames(counts)[max.value.col] 
max.counts <- counts[cbind(1:nrow(counts), max.value.col)] 
paste(max.value, max.counts, sep = ", ") 
# [1] "blue, 6" "blue, 5" "blue, 5" "blue, 5" "blue, 5" "blue, 4" 

Если вы хотите, чтобы получить имена всех столбцов, если есть связь, следующий будет работать, но может занять некоторое время (не уверен о выполнении apply в этом случае)

max.value.all.cols <- counts == counts[cbind(1:nrow(counts), max.value.col)] 
paste(
    apply(max.value.all.cols, 1, function(r) paste(paste(colnames(counts)[r],  
     collapse = ", "))), 
    max.counts, sep = ", ") 
+1

'vapply (значения, функция (значение) rowSums (dat == value), numeric (nrow (dat)))' может даже быть быстрее, чем 'sapply' –

+0

@konvas Если есть связь между максимальными значениями,' max. col', кажется, выбирает один из них произвольно. Существует ли эквивалент 'max.col', который определяет все максимальные значения? – Khashaa

+0

@RichardScriven Хорошая точка! Это должно улучшить скорость совсем немного. – konvas

0

Это актуальное решение для обработки данных. Я думаю. Использует data.table-х быстро .N для подсчета частоты строк

library(data.table) 

flip <- data.table(t(mat)) 

tally <- lapply(names(flip), 
       function(x) { 
        setnames(flip[, .N, by=eval(x)][order(-N)][1,], 
          c('clr', 'N')) }) 
do.call(rbind, tally) 

#  clr N 
# 1: blue 6 
# 2: blue 5 
# 3: blue 5 
# 4: blue 5 
# 5: blue 5 
# 6: blue 4 

Я принимаю матрицу и транспонировать ее, а затем делать отсчеты по каждому колонку (т.е. каждой строки исходной матрицы). Требуется бит setnames, чтобы мы могли легко свернуть результаты вместе, но если вы счастливы получить результаты в форме списка, это не требуется.

Я использовал те же данные, что и другие:

mat <- 
matrix(c("blue","red","blue","blue","blue","red","green","blue","blue", 
      "green","red","blue","blue","blue","red","green","blue","blue", 
      "yellow","red","blue","blue","blue","red","green","blue","blue", 
      "red","red","blue","blue","blue","red","green","blue","blue", 
      "blue","red","green","blue","blue","red","green","blue","blue", 
      "green","red","green","blue","blue","red","green","blue","blue"), 
     ncol = 9, byrow = TRUE) 
+0

eh, но операция t() медленна на больших матрицах. неважно – arvi1000