Зачем создавать каркасные разделители, повышающие Ave функцию? - PullRequest
0 голосов
/ 26 февраля 2020

У меня проблемы с использованием df с 2 столбцами и 4.632.351 строками.

Столбцами являются Имя и Пол.

Я хочу подсчитать дублирующиеся имена и добавить в новый столбец, поэтому я использую функцию ave

data2$NmbCmpDup <- as.numeric(ave(data2$Nombre,data2$Nombre,  FUN = length))

Но это занимает так много времени, может быть, 3 часа, поэтому я останавливаю запущенный процесс.

Затем с помощью caret я создал раздел, чтобы я мог работать с меньшими затратами строки ..

createDataPartition(data$Genero, p = 0.01, list=F)

Итак, я создал 1% -ый раздел и использую функцию ave

data.p = createDataPartition(data$Genero, p = 1, list=F)
data2 = data[data.p,]
data2$NmbCmpDup <- as.numeric(ave(data2$Nombre,data2$Nombre,  FUN = length))

А затем функция ave увеличится до 10 секунд .. Итак, я попробовал с 5 % и все еще был очень быстрым, поэтому я добавил все больше и больше процентов, пока не сделал 100% -ый раздел, а функция ave заняла всего 2 минуты.

Хорошо, теперь я хотел бы знать, почему ..? есть мысли?

1 Ответ

1 голос
/ 26 февраля 2020

Функция медленная, потому что вам не нужно использовать ave для получения длины. Вы можете составить таблицу, а затем заполнить столбец. Ниже приведены 3 решения, которые должны быть быстрее, чем у вас есть. Также я не уверен, является ли ваш столбец с именем Nombre фактором или символом.

Первый пример:

set.seed(100)
data2 = data.frame(Nombre = sample(LETTERS,2e6,replace=TRUE),
Genero = sample(c("M","F"),2e6,replace=TRUE),stringsAsFactors=FALSE)

Функции, я думаю, data.table все еще не оптимальны, но мы можем работать с ним сейчас:

f1 = function(data2){
data2$NmbCmpDup = as.numeric(ave(data2$Nombre,data2$Nombre,FUN=length))
data2
}
f2 = function(data2){
data2$NmbCmpDup = as.numeric(table(data2$Nombre)[data2$Nombre])
data2
}
f3 = function(data2){
tab = as.data.table(data2)[,.N,by=Nombre]
data2$NmbCmpDup = tab$N[match(data2$Nombre,tab$Nombre)]
data2
}

Мы проверяем это:

library(microbenchmark)
library(data.table)
Unit: milliseconds
      expr       min        lq     mean   median       uq      max neval cld
 f1(data2) 584.73459 626.12690 670.0398 643.3440 687.0022 911.2973   100   c
 f2(data2) 175.23440 196.36763 229.3775 213.6137 237.8333 407.0434   100  b 
 f3(data2)  73.35966  94.32614 119.9301 104.9643 119.7894 335.6455   100 a  

Так что просто использование таблицы или data.table намного быстрее, чем функция Ave.

...