这里有几个问题。
第一
:
# Warning message:
# In rsqlite_fetch(res@ptr, n = n) :
# Don't need to call dbFetch() for statements, only for queries
这是一个警告,不是错误。事实上,这似乎是
RSQLite
,并在公开发行中引用:
https://github.com/r-dbi/RSQLite/issues/227
.
(对于清洁度,我将在本答案的其余部分中从输出中删除它,尽管它发生在每个非-
select
查询。)
第二
,
RSQLite公司
处理数据库,句号。它对R环境中的变量没有意见或意识,因此没有证据表明R中的变量是数据库表的即时和永久表示。(有类似的方法使用
dbplyr
那个
做
粗略地说,就是这样。)
为了在R和某种形式的SQL查询之间提供这种类型的联系,有
sqldf
这允许您对R变量进行查询,就像它们是实际的SQL表一样。当您执行这样的查询时,它会获取数据。框架,将其插入到临时数据库表中(是否
RSQLite公司
,运行SQL代码,然后返回所需内容。
第三
:尽管有这种明显的联系,但它的功能相当强大,因为它不会产生
side-effects
在R环境中。这意味着,如果希望以R可以使用的方式存储生成的数据,则需要将新表显式捕获到R变量中。
例如:
library(sqldf)
(mt <- mtcars[1:5,1:5])
# mpg cyl disp hp drat
# Mazda RX4 21.0 6 160 110 3.90
# Mazda RX4 Wag 21.0 6 160 110 3.90
# Datsun 710 22.8 4 108 93 3.85
# Hornet 4 Drive 21.4 6 258 110 3.08
# Hornet Sportabout 18.7 8 360 175 3.15
更新后,原始数据保持不变。
sqldf('update mt set cyl=5 where cyl>5')
mt
# mpg cyl disp hp drat
# Mazda RX4 21.0 6 160 110 3.90
# Mazda RX4 Wag 21.0 6 160 110 3.90
# Datsun 710 22.8 4 108 93 3.85
# Hornet 4 Drive 21.4 6 258 110 3.08
# Hornet Sportabout 18.7 8 360 175 3.15
通过包含一个
select * from ...
在您的呼叫中
sqldf
:
mt2 <- sqldf(c('update mt set cyl=5 where cyl>5', 'select * from mt'))
mt2
# mpg cyl disp hp drat
# 1 21.0 5 160 110 3.90
# 2 21.0 5 160 110 3.90
# 3 22.8 4 108 93 3.85
# 4 21.4 5 258 110 3.08
# 5 18.7 5 360 175 3.15
(在这种情况下,我将其保存到
mt2
,但您可以轻松地将其改写。)
所有这些都以各种形式在
sqldf
FAQ 8
,“8.为什么我在更新方面遇到问题?”
编辑
似乎有一些误解
sqldf
诸如此类。
-
您正在创建
db
直接SQL查询的句柄(不是
sqldf
),但你从不使用它。正如您稍后将看到的,(a)使用
dbExecute
(和相关功能)
数据库
手柄,或(b)使用
sqldf
,无需
dbConnect
还有朋友。
-
使用时
sqldf
在…上
每个和每个
致电至
sqldf
它有一个
完整的副本
将变量的当前实例导入数据库。(这既有帮助,有时效率也很低。对于较小的数据集,可能感觉不到损失的时间,但仍然…)所以当你一直提到
桌子
films
,它忽略了
d
您创建了,因为它无法推断您在其调用之外尝试做什么。。。它只是复制、查询和丢弃。
# assuming this is something like what you do ... but it doesn't matter
films <- read.csv("films.csv", ...)
# `-<---<---<---<---<---<---<---<---<---<---<---<---<---<---<-+-<--.
db <- dbConnect(SQLite(), "tempdb") # not used in sqldf ^ \
dbWriteTable(db, "films", films, overwrite=TRUE) # never used ^ \
# `--- is referring to --->--->--->--' \
d <- sqldf(c('update films set movie_title=lower(movie_title)', # \
'select * from films')) # \
# \ `--- (internal to sqldf) ^
# `--- refers to the original 'films' --->--->--->--'
选项1
,使用
RSQLite公司
功能,而不是
sqldf
:
db <- dbConnect(SQLite(), "tempdb")
dbWriteTable(db,"films",films, overwrite=TRUE)
dbExecute(db, 'update films set actor_3_name=lower(actor_3_name)')
# `--- repeat for all updates
films <- dbGetQuery(db, 'select * from films')
选择2
,(不是我的首选)使用前一行中创建的变量:
films <- read.csv("films.csv", ...)
# `--<---<---<---<---<---<---<---<---<---<---<---<---<---<---<---<---<-.
d <- sqldf(c('update films set movie_title=lower(movie_title)', # \
'select * from films')) # \
#\ \ `--- (internal to sqldf) ^
# \ `--- refers to original 'films' --->--->--->--->--'
# `--<---<---<---<---<---<---<---<---<---<---<---<---<---<---<---<--.
d <- sqldf(c('update d set actor_3_name=lower(actor_3_name)', # \
'select * from d')) # \
# \ `--- (internal to sqldf) ^
# `--- refers to previously-created 'd' --->--->--->'
# (repeat for other updates)
选项3
,始终引用/覆盖原始
电影
变量:
films <- read.csv("films.csv", ...)
# `--<---<---<---<---<---<---<---<---<---<---<---+--<---<---<---<---<---.
films <- sqldf(c('update films set movie_title=lower(movie_title)', # \
'select * from films')) # \
# \ \ `--- (internal to sqldf) ^
# \ ` --- refers to the first 'films' -->--->--->--'
# `-<---<---<---<---<---<---<---<---<---<---<---+--<---<---<---<---<--.
films <- sqldf(c('update films set actor_3_name=lower(actor_3_name)', # \
'select * from films')) # \
# \ `--- (internal to sqldf) ^
# ` --- refers to the second 'films' -->--->--->-'
# (repeat for other updates)
-
sqldf
效率低下。每次你打电话给
sqldf
,它将整个数据集复制到临时表中。每一个时间通过将所有查询字符串组合到一个调用中,可以减少一些开销,如下所示:
films <- read.csv("films.csv", ...)
films <- sqldf(c('update films set actor_3_name=lower(actor_3_name)',
'update films set actor_2_name=lower(actor_2_name)',
'update films set actor_1_name=lower(actor_1_name)',
'update films set director_name=lower(director_name)',
'select * from films'))
-
SQL效率低下。对于这个问题,您的原始代码可能会被简化(这很好),但如果不是这样的话,那么接下来就是了。由于您似乎根本没有调整更新,因此可以将数据清理合并到一个更新中。(这可用于
数据库执行
也是如此。)
films <- read.csv("films.csv", ...)
films <- sqldf(c('update films set actor_3_name=lower(actor_3_name),
actor_3_name=lower(actor_3_name),
actor_2_name=lower(actor_2_name),
actor_1_name=lower(actor_1_name),
director_name=lower(director_name)',
'select * from films'))
-
你真的需要SQL吗?这可以在R中轻松/快速完成:
films <- read.csv("films.csv", ...)
films <- within(films, {
actor_3_name <- tolower(actor_3_name)
actor_2_name <- tolower(actor_2_name)
actor_1_name <- tolower(actor_1_name)
director_name <- tolower(director_name)
})