为什么要创建插入符号分区提升 ave 函数?
Why creating a caret partition boost ave function?
我在使用 2 列和 4.632.351 行的 df 时遇到问题。
列是姓名和性别。
我想计算重复名称并添加到新列中,所以我使用 ave 函数
data2$NmbCmpDup <- as.numeric(ave(data2$Nombre,data2$Nombre, FUN = length))
但是需要很长时间,可能需要 3 个小时,所以我停止了 运行 过程。
然后我用插入符创建了一个分区,所以我可以使用更少的行..
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 分钟。
好的,现在我想知道为什么..?有什么想法吗?
函数速度较慢,因为您不需要使用ave来获取长度。您可以 table 然后填充该列。以下是 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
所以仅使用 table 或 data.table 比 ave 函数快得多。
我在使用 2 列和 4.632.351 行的 df 时遇到问题。
列是姓名和性别。
我想计算重复名称并添加到新列中,所以我使用 ave 函数
data2$NmbCmpDup <- as.numeric(ave(data2$Nombre,data2$Nombre, FUN = length))
但是需要很长时间,可能需要 3 个小时,所以我停止了 运行 过程。
然后我用插入符创建了一个分区,所以我可以使用更少的行..
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 分钟。
好的,现在我想知道为什么..?有什么想法吗?
函数速度较慢,因为您不需要使用ave来获取长度。您可以 table 然后填充该列。以下是 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
所以仅使用 table 或 data.table 比 ave 函数快得多。