r - 使用 data.table 包,哪个将提供最快的用户时间?(R 编程)
问题描述
我在一次在线培训的测试中遇到了这个问题。我只是通过反复试验得到了它。很可能,我做错了什么,因为我是 R 编程的初学者。
这是问题:
在阅读我的 R 代码之前,请注意,在最后一部分中,我必须将所有列转换为数字,因为没有它,我会收到以下消息:
“rowMeans(DT) 中的错误:‘x’必须是数字。”
在测试中,我教授的解决方案是:“ DT[,mean(pwgtp15), by=SEX] ”
使用我的 R 代码,正确答案是mean(DT$pwgtp15, by=DT$SEX)。
我得到这个输出:
我的疑问是,也许我的工作方式DT[,mean(pwgtp15), by=SEX]会产生缓慢的计算。
为此,我用
DT <- data.frame(data.matrix(DT))
哪一个是正确答案?教授解决方案?我的答案?另一个?
这是我的代码:
#THE SOLUTION IS DT[,mean(pwgtp15), by=SEX]
#HOWEVER, my solution is mean(DT$pwgtp15, by=DT$SEX)
install.packages("data.table")
library("data.table")
# the example below runs 100 times
download.file("https://d396qusza40orc.cloudfront.net/getdata%2Fdata%2Fss06pid.csv", destfile = "ACS.csv")
DT <- fread("ACS.csv", sep = ",")
counter<- 0
myName<-"DT[,mean(pwgtp15), by=SEX]"
for (i in 1:100)
{
a<- Sys.time()
DT[,mean(pwgtp15), by=SEX]
b<-Sys.time()
myTime<-b-a
counter<- counter + myTime
}
cat("counter is: ", counter, "myName is: ", myName, "\n")
counter<- 0
myName<-"mean(DT[DT$SEX==1,]$pwgtp15);mean(DT[DT$SEX==2,]$pwgtp15)"
for (i in 1:100)
{
a<- Sys.time()
mean(DT[DT$SEX==1,]$pwgtp15); mean(DT[DT$SEX==2,]$pwgtp15)
b<-Sys.time()
myTime<-b-a
counter<- counter + myTime
}
cat("counter is: ", counter, "myName is: ", myName, "\n")
counter<- 0
myName<-"sapply(split(DT$pwgtp15,DT$SEX),mean)"
for (i in 1:100)
{
a<- Sys.time()
sapply(split(DT$pwgtp15,DT$SEX),mean)
b<-Sys.time()
myTime<-b-a
counter<- counter + myTime
}
cat("counter is: ", counter, "myName is: ", myName, "\n")
counter<- 0
myName<-"tapply(DT$pwgtp15, DT$SEX, mean)"
for (i in 1:100)
{
a<- Sys.time()
tapply(DT$pwgtp15, DT$SEX, mean)
b<-Sys.time()
myTime<-b-a
counter<- counter + myTime
}
cat("counter is: ", counter, "myName is: ", myName, "\n")
counter<- 0
myName<-"mean(DT$pwgtp15, by=DT$SEX)"
for (i in 1:100)
{
a<- Sys.time()
mean(DT$pwgtp15, by=DT$SEX)
b<-Sys.time()
myTime<- b-a
counter<- counter + myTime
}
cat("counter is: ", counter, "myName is: ", myName, "\n")
#We convert the entire DATAFRAME to numeric
#Otherwise rowmeans will not work
DT <- data.frame(data.matrix(DT))
counter<- 0
myName<-"rowMeans(DT)[DT$SEX==1];rowMeans(DT)[DT$SEX==2]"
for (i in 1:100)
{
a<- Sys.time()
rowMeans(DT)[DT$SEX==1];rowMeans(DT)[DT$SEX==2]
b<-Sys.time()
myTime<- b-a
counter<- counter + myTime
}
cat("counter is: ", counter, "myName is: ", myName, "\n")
解决方案
如前所述,问题的答案选择不会产生相同的结果。by to没有命名参数base::mean()
。由于该函数允许向其他方法传递或从其他方法传递更多参数,因此它不会通过参数出错。因此,由于它不会按 等因素进行拆分/子集DT$SEX
,因此这将是最快的时间。
此外,其他方法返回较慢的时间是有原因的:
tapply(...)
,sapply(split(...))
,rowMeans(...)
所有都是直接或间接应用的家庭成员,它们是隐藏循环而不是完全矢量化的计算。此外,
rowMeans
它是一个包装器,apply
并且被调用了两次。另外,apply
众所周知,将整个数据框/表转换为矩阵,我们应该注意@DavidArenburg 的警告:如果您正在使用
data.frame
s,请忘记有一个名为的函数apply
——无论你做什么——都不要使用它。尤其是边距为 1(此函数唯一好的用例是在列上操作matrix
- 边距为 2)。mean(...); mean(...)
这对子集数据帧进行了两次调用。逻辑索引
[
返回数据框的所有列,然后$
选择最终的数字列mean()
。事实上,如果你运行向量子集而不是返回所有列的数据框子集,它会更快,也许是最快的:
mean(DT$pwgtp15[DT$SEX==1]);mean(DT$pwgtp15[DT$SEX==2]) a <- Sys.time() DT[,mean(pwgtp15), by=SEX] b <- Sys.time() myTime <- b-a myTime # Time difference of 0.01888704 secs # Time difference of 0.03294992 secs # Time difference of 0.03321409 secs a <- Sys.time() mean(DT$pwgtp15[DT$SEX==1]);mean(DT$pwgtp15[DT$SEX==2]) b <- Sys.time() myTime <- b-a myTime # Time difference of 0.006003857 secs # Time difference of 0 secs # Time difference of 0 secs
推荐阅读
- python - 在 gspread 中更新工作表名称的功能不起作用
- javascript - 如何让我们的动画一开始不执行,点击后才执行?
- php - pHp 问题:“等待本地主机”:可能是无限循环问题?
- python - Python 3 Pandas:计算列中出现相同的条目
- python - 对于一个简单的 API,我的 Pandas Read_JSON 出了什么问题?
- python - 我做了一个功能,在我的井字游戏中的每一步之后都会改变玩家,但它似乎不起作用
- automation - 运行 terraform init、terraform plan 或 apply 时出现无效字符错误
- python - Python:使用谷歌提供的代码段将视频上传到 youtube 不起作用
- spring-boot - 如何将我的 .graphqls 文件拆分为多个文件?
- nuxt.js - 在 Nuxt/Tailwind 项目中加载自定义字体