我写了一个函数来更方便地访问我在工作中使用的数据库:而不是需要输入传统的SQL命令,我只能在数据库中列出一个表的名称,该函数会自动将整个表加载到R,我分配给一个数据帧。加载时,某些类型 date 和 logical 的列显示为 integer 或 character ,所以我的功能也识别并重新铸造它们。
不幸的是,最近我的查询运行速度变慢了,有些甚至还没完成。我不知道这是因为数据库问题还是代码问题,但我只能控制后者,所以我想我会得到一些反馈并找出是否可以使某些部分更有效率。我知道的一部分效率不高是查询的*部分 - 我很少需要每一列,但我经常不知道我需要提前哪些,因为有我可以加载许多不同的表,*是我知道的唯一选择语句将适用于所有这些表。不过,我对任何其他效率见解持开放态度。我将介绍这个功能:
GetFinderTable <- function(table) {
if (missing(table))
stop("ERROR: Table missing")
if (!table %in% c(*table names*))
stop("ERROR: Table not found in Finder Database")
query <- "*"
该函数的第一部分执行基本错误检查,以确保表名存在并且是数据库中的表之一。我将*值赋给“查询” - 我考虑过扩展它以为这个变量提供其他列名,但这将非常依赖于表。
LoadPackages(c('DBI', 'RMySQL', 'glue', 'magrittr', 'rlist'))
db <- dbConnect(MySQL(), user = -private-, password = -private-, host = -private-, dbname = -private-)
df <- dbGetQuery(db, glue('select {query} from {table}'))
dbDisconnect(db)
LoadPackages 是我为简化包管理而编写的另一个自定义函数 - 它将根据需要安装,更新或附加列出的包。无论谁运行此脚本,都将安装必要的软件包。接下来的三行实际上是在查询数据库。我使用 glue 因为它更方便,但我想知道与 paste 相比效率是否低。
cols <- apply(df, 2, function(x) (grepl("[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$", na.omit(x)) %>% all))
%>% which
size <- length(cols)
if (size > 0) {
if (size == 1)
df[,cols] %<>% as.Date
else
df[,cols] %<>% lapply(as.Date)
}
cols <- apply(df, 2, function(x) (grepl("^[0-1]$", na.omit(x)) %>% all)) %>% which %>%
list.append(apply(df, 2, function(x) (grepl("False|True", na.omit(x)) %>% all)) %>% which)
size <- length(cols)
if (size > 0) {
if (size == 1)
df[,cols] %<>% as.logical
else
df[,cols] %<>% lapply(as.logical)
}
return(df)
}
这是我希望提高效率的地方。接下来的几行隔离日期列(通过检查它们是否与R的日期格式匹配)和逻辑列(通过查看列是否仅包含0和1或“True”和“False”)。我偶然发现使用lapply的危险,只有一列需要重铸,因此为什么我有 if 条件。重铸后,将返回数据帧。
非常感谢任何有关如何提高功能效率的见解。我花了太长时间等待这些查询完成!