使用带引号的 RSQLite 加载数据
Loading data with RSQLite which has quoted values
我正在尝试使用 RSQLite 包(我也尝试过 sqldf 包)将一个大的 csv 文件加载到 SQL 精简版数据库中。该文件包含所有英国邮政编码和它们的各种查找值。
我想避免将其加载到 R 中,而是直接将其加载到数据库中。虽然这对于这个任务来说并不是绝对必要的,但我想这样做是为了让技术准备好处理那些不适合内存的大文件,如果我将来必须处理它们的话。
不幸的是,csv 提供了双引号中的值,dbWriteTable 函数似乎无法以任何形式去除或忽略它们。这是文件的下载位置:http://ons.maps.arcgis.com/home/item.html?id=3548d835cff740de83b527429fe23ee0
这是我的代码:
# Load library
library("RSQLite")
# Create a temporary directory
tmpdir <- tempdir()
# Set the file name
file <- "data\ONSPD_MAY_2017_UK.zip"
# Unzip the ONS Postcode Data file
unzip(file, exdir = tmpdir )
# Create a path pointing at the unzipped csv file
ONSPD_path <- paste0(tmpdir,"\ONSPD_MAY_2017_UK.csv")
# Create a SQL Lite database connection
db_connection <- dbConnect(SQLite(), dbname="ons_lkp_db")
# Now load the data into our SQL lite database
dbWriteTable(conn = db_connection,
name = "ONS_PD",
value = ONSPD_path,
row.names = FALSE,
header = TRUE,
overwrite = TRUE
)
# Check the data upload
dbListTables(db_connection)
dbGetQuery(db_connection,"SELECT pcd, pcd2, pcds from ONS_PD LIMIT 20")
遇到这个问题,我找到了一个参考教程(https://www.r-bloggers.com/r-and-sqlite-part-1/),它推荐使用 sqldf 包,但不幸的是,当我尝试使用 sqldf 中的相关功能时(read.csv.sql) 然后我用双引号遇到同样的问题。
在将 csv 文件导入 sql 系统时,这感觉是一个相当普遍的问题,大多数导入工具都能够处理双引号,所以我很惊讶遇到这个问题(除非我'在此过程中,我错过了关于该问题的明显帮助文件。
编辑 1
这是我的 csv 文件中的一些示例数据,采用 SQL table:
的 dput 输出形式
structure(list(pcd = c("\"AB1 0AA\"", "\"AB1 0AB\"", "\"AB1 0AD\"",
"\"AB1 0AE\"", "\"AB1 0AF\""), pcd2 = c("\"AB1 0AA\"", "\"AB1 0AB\"",
"\"AB1 0AD\"", "\"AB1 0AE\"", "\"AB1 0AF\""), pcds = c("\"AB1 0AA\"",
"\"AB1 0AB\"", "\"AB1 0AD\"", "\"AB1 0AE\"", "\"AB1 0AF\"")), .Names = c("pcd",
"pcd2", "pcds"), class = "data.frame", row.names = c(NA, -5L))
编辑 2
这是我在 sqldf 的 read.csv.sql 函数中使用过滤器参数的尝试(请注意,Windows 用户需要为此安装 rtools)。不幸的是,这似乎仍然没有从我的数据中删除引号,尽管它确实神秘地删除了所有空格。
library("sqldf")
sqldf("attach 'ons_lkp_db' as new")
db_connection <- dbConnect(SQLite(), dbname="ons_lkp_db")
read.csv.sql(ONSPD_path,
sql = "CREATE TABLE ONS_PD AS SELECT * FROM file",
dbname = "ons_lkp_db",
filter = 'tr.exe -d ^"'
)
dbGetQuery(db_connection,"SELECT pcd, pcd2, pcds from ONS_PD LIMIT 5")
此外,感谢那些认为这不是 Stack Overflow 范围内的编程问题的人的近距离投票(?!)。
老实说,我找不到任何方法来解决这个问题。
sqldf 文档告诉
“因此,.csv 文件的一个限制是引号
在文件中不被视为特殊的,因此数据字段中的逗号如
"Smith, James"
将被视为字段分隔符,引号将作为数据的一部分输入
可能不是预期的
所以,据我所知似乎没有解决方案。
一种可能的次优方法(除了在文本编辑器中明显的查找和替换)
就是使用 SQL 这样的命令
dbSendQuery(db_connection,"UPDATE ONS_PD SET pcd = REPLACE(pcd, '\"', '')")
RSQLite
包中的 CSV 导入器派生自 sqlite3 shell,它本身在导入 CSV 文件时似乎不支持引用值 (How to import load a .sql or .csv file into SQLite?, doc) .你可以使用 readr::read_delim_chunked()
:
callback <- function(data) {
name <- "ONS_PD"
exists <- dbExistsTable(con, name)
dbWriteTable(con, name, data, append = exists)
}
readr::read_delim_chunked(ONSPD_path, callback, ...)
用您的 CSV 文件所需的任何额外参数替换 ...
。
使用 sqldf 包中的 read.csv.sql
和 filter
参数,并提供任何实用程序来去除双引号或将它们转换为空格。
这个问题没有提供完全可重现的最小示例,但我在下面提供了一个。如果您使用 read.csv.sql
来选择行或列的子集,那么只需添加适当的 sql
参数即可。
首先设置测试输入数据,然后尝试下面显示的任何单行解决方案。假设 Windows,确保 tr 实用程序(在 R 的 Rtools 发行版中找到)或第三方 csvfix 实用程序(找到 here and for Linux also see this)或 trquote2space.vbs vbscript 实用程序(请参阅末尾的注释)已打开你的路径:
library(sqldf)
cat('a,b\n"1","2"\n', file = "tmp.csv")
# 1 - corrected from FAQ
read.csv.sql("tmp.csv", filter = "tr.exe -d '^\"'")
# 2 - similar but does not require Windows cmd quoting
read.csv.sql("tmp.csv", filter = "tr -d \42")
# 3 - using csvfix utility (which must be installed first)
read.csv.sql("tmp.csv", filter = "csvfix echo -smq")
# 4 - using trquote2space.vbs utility as per Note at end
read.csv.sql("tmp.csv", filter = "cscript /nologo trquote2space.vbs")
其中任何一个给出:
a b
1 1 2
您还可以使用任何其他合适的语言或实用程序。例如,可以使用您的 Powershell 建议,尽管我怀疑 tr 和 csvfix 等专用实用程序会 运行 更快。
上面的第一个解决方案是从常见问题解答中更正的。 (它在多年前编写常见问题解答时确实有效,但现在在 Windows 10 中对其进行测试,它似乎需要指定的更改,或者降价可能无法从 Google 代码的移动中完好无损,它最初所在的位置,到 github,它使用稍微不同的降价风格。)
对于 Linux,tr 本身可用,尽管引用不同于 Windows,甚至可以依赖于 shell。 csvfix 在 Linux 上也可用,但必须安装。上面显示的 csvfix 示例在 Windows 和 Linux 上的工作方式相同。 vbscript 显然特定于 Windows.
注意:sqldf 附带一个用 vbscript 编写的 mini-tr 实用程序。如果将相关行更改为:
Dim sSearch : sSearch = chr(34)
Dim sReplace : sReplace = " "
并将名称更改为 trquote2space.vbs 然后您将有一个 Windows 特定的实用程序来将双引号更改为空格。
我正在尝试使用 RSQLite 包(我也尝试过 sqldf 包)将一个大的 csv 文件加载到 SQL 精简版数据库中。该文件包含所有英国邮政编码和它们的各种查找值。
我想避免将其加载到 R 中,而是直接将其加载到数据库中。虽然这对于这个任务来说并不是绝对必要的,但我想这样做是为了让技术准备好处理那些不适合内存的大文件,如果我将来必须处理它们的话。
不幸的是,csv 提供了双引号中的值,dbWriteTable 函数似乎无法以任何形式去除或忽略它们。这是文件的下载位置:http://ons.maps.arcgis.com/home/item.html?id=3548d835cff740de83b527429fe23ee0
这是我的代码:
# Load library
library("RSQLite")
# Create a temporary directory
tmpdir <- tempdir()
# Set the file name
file <- "data\ONSPD_MAY_2017_UK.zip"
# Unzip the ONS Postcode Data file
unzip(file, exdir = tmpdir )
# Create a path pointing at the unzipped csv file
ONSPD_path <- paste0(tmpdir,"\ONSPD_MAY_2017_UK.csv")
# Create a SQL Lite database connection
db_connection <- dbConnect(SQLite(), dbname="ons_lkp_db")
# Now load the data into our SQL lite database
dbWriteTable(conn = db_connection,
name = "ONS_PD",
value = ONSPD_path,
row.names = FALSE,
header = TRUE,
overwrite = TRUE
)
# Check the data upload
dbListTables(db_connection)
dbGetQuery(db_connection,"SELECT pcd, pcd2, pcds from ONS_PD LIMIT 20")
遇到这个问题,我找到了一个参考教程(https://www.r-bloggers.com/r-and-sqlite-part-1/),它推荐使用 sqldf 包,但不幸的是,当我尝试使用 sqldf 中的相关功能时(read.csv.sql) 然后我用双引号遇到同样的问题。
在将 csv 文件导入 sql 系统时,这感觉是一个相当普遍的问题,大多数导入工具都能够处理双引号,所以我很惊讶遇到这个问题(除非我'在此过程中,我错过了关于该问题的明显帮助文件。
编辑 1
这是我的 csv 文件中的一些示例数据,采用 SQL table:
的 dput 输出形式structure(list(pcd = c("\"AB1 0AA\"", "\"AB1 0AB\"", "\"AB1 0AD\"",
"\"AB1 0AE\"", "\"AB1 0AF\""), pcd2 = c("\"AB1 0AA\"", "\"AB1 0AB\"",
"\"AB1 0AD\"", "\"AB1 0AE\"", "\"AB1 0AF\""), pcds = c("\"AB1 0AA\"",
"\"AB1 0AB\"", "\"AB1 0AD\"", "\"AB1 0AE\"", "\"AB1 0AF\"")), .Names = c("pcd",
"pcd2", "pcds"), class = "data.frame", row.names = c(NA, -5L))
编辑 2
这是我在 sqldf 的 read.csv.sql 函数中使用过滤器参数的尝试(请注意,Windows 用户需要为此安装 rtools)。不幸的是,这似乎仍然没有从我的数据中删除引号,尽管它确实神秘地删除了所有空格。
library("sqldf")
sqldf("attach 'ons_lkp_db' as new")
db_connection <- dbConnect(SQLite(), dbname="ons_lkp_db")
read.csv.sql(ONSPD_path,
sql = "CREATE TABLE ONS_PD AS SELECT * FROM file",
dbname = "ons_lkp_db",
filter = 'tr.exe -d ^"'
)
dbGetQuery(db_connection,"SELECT pcd, pcd2, pcds from ONS_PD LIMIT 5")
此外,感谢那些认为这不是 Stack Overflow 范围内的编程问题的人的近距离投票(?!)。
老实说,我找不到任何方法来解决这个问题。 sqldf 文档告诉 “因此,.csv 文件的一个限制是引号 在文件中不被视为特殊的,因此数据字段中的逗号如 "Smith, James" 将被视为字段分隔符,引号将作为数据的一部分输入 可能不是预期的
所以,据我所知似乎没有解决方案。
一种可能的次优方法(除了在文本编辑器中明显的查找和替换) 就是使用 SQL 这样的命令
dbSendQuery(db_connection,"UPDATE ONS_PD SET pcd = REPLACE(pcd, '\"', '')")
RSQLite
包中的 CSV 导入器派生自 sqlite3 shell,它本身在导入 CSV 文件时似乎不支持引用值 (How to import load a .sql or .csv file into SQLite?, doc) .你可以使用 readr::read_delim_chunked()
:
callback <- function(data) {
name <- "ONS_PD"
exists <- dbExistsTable(con, name)
dbWriteTable(con, name, data, append = exists)
}
readr::read_delim_chunked(ONSPD_path, callback, ...)
用您的 CSV 文件所需的任何额外参数替换 ...
。
使用 sqldf 包中的 read.csv.sql
和 filter
参数,并提供任何实用程序来去除双引号或将它们转换为空格。
这个问题没有提供完全可重现的最小示例,但我在下面提供了一个。如果您使用 read.csv.sql
来选择行或列的子集,那么只需添加适当的 sql
参数即可。
首先设置测试输入数据,然后尝试下面显示的任何单行解决方案。假设 Windows,确保 tr 实用程序(在 R 的 Rtools 发行版中找到)或第三方 csvfix 实用程序(找到 here and for Linux also see this)或 trquote2space.vbs vbscript 实用程序(请参阅末尾的注释)已打开你的路径:
library(sqldf)
cat('a,b\n"1","2"\n', file = "tmp.csv")
# 1 - corrected from FAQ
read.csv.sql("tmp.csv", filter = "tr.exe -d '^\"'")
# 2 - similar but does not require Windows cmd quoting
read.csv.sql("tmp.csv", filter = "tr -d \42")
# 3 - using csvfix utility (which must be installed first)
read.csv.sql("tmp.csv", filter = "csvfix echo -smq")
# 4 - using trquote2space.vbs utility as per Note at end
read.csv.sql("tmp.csv", filter = "cscript /nologo trquote2space.vbs")
其中任何一个给出:
a b
1 1 2
您还可以使用任何其他合适的语言或实用程序。例如,可以使用您的 Powershell 建议,尽管我怀疑 tr 和 csvfix 等专用实用程序会 运行 更快。
上面的第一个解决方案是从常见问题解答中更正的。 (它在多年前编写常见问题解答时确实有效,但现在在 Windows 10 中对其进行测试,它似乎需要指定的更改,或者降价可能无法从 Google 代码的移动中完好无损,它最初所在的位置,到 github,它使用稍微不同的降价风格。)
对于 Linux,tr 本身可用,尽管引用不同于 Windows,甚至可以依赖于 shell。 csvfix 在 Linux 上也可用,但必须安装。上面显示的 csvfix 示例在 Windows 和 Linux 上的工作方式相同。 vbscript 显然特定于 Windows.
注意:sqldf 附带一个用 vbscript 编写的 mini-tr 实用程序。如果将相关行更改为:
Dim sSearch : sSearch = chr(34)
Dim sReplace : sReplace = " "
并将名称更改为 trquote2space.vbs 然后您将有一个 Windows 特定的实用程序来将双引号更改为空格。