sqlite 如何将 Dataframe 列表插入到数据库中?

jyztefdp  于 2022-11-24  发布在  SQLite
关注(0)|答案(2)|浏览(231)

我想使用dplyr包从data.frame列表中创建一个SQLite数据库。看起来dplyr::copy_to是我需要的。我认为问题与NSE有关。另请参阅dplyr with databases的小插图。

data(iris)
data(cars)

res <- list("iris" = iris, "cars" = cars)

my_db <- dplyr::src_sqlite(paste0(tempdir(), "/foobar.sqlite3"),
                       create = TRUE)

lapply(res, function(x) dplyr::copy_to(my_db, x))

错误:表x已存在。

vcudknz3

vcudknz31#

这是因为默认表名基于R中数据框的名称。使用lapply时,它采用索引名称。
dplyr::copy_to.src_sql的文档包含:

## S3 method for class 'src_sql'
copy_to(dest, df, name = deparse(substitute(df)),
  types = NULL, temporary = TRUE, unique_indexes = NULL, indexes = NULL,
  analyze = TRUE, ...)

name = deparse(substitute(df))显示表名的来源。
我们可以看到它会变成什么:

res <- list("iris" = iris, "cars" = cars)
tmp = lapply(res, function(x) print(deparse(substitute(x))))
#> [1] "X[[i]]"
#> [1] "X[[i]]"

SQLite源中表的nameX[[i]];一旦执行了第一行,表就已经存在了。
我们可以通过使用显式for循环并辅助传递名称来解析,或者通过在索引号上使用lapply来解析。
例如:

res <- list("iris" = iris, "cars" = cars)
my_db <- dplyr::src_sqlite(paste0(tempdir(), "/foobar.sqlite3"),
                           create = TRUE)
lapply(seq_along(res), function(i, l){dplyr::copy_to(my_db, l[[i]], names(l)[[i]])}, l = res)
my_db %>% tbl("iris") %>% head

#> Source:   query [?? x 5]
#> Database: sqlite 3.8.6 
#> 
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#>          <dbl>       <dbl>        <dbl>       <dbl>   <chr>
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa

my_db %>% tbl("cars") %>% head

#> Source:   query [?? x 2]
#> Database: sqlite 3.8.6 
#> 
#>   speed  dist
#>   <dbl> <dbl>
#> 1     4     2
#> 2     4    10
#> 3     7     4
#> 4     7    22
#> 5     8    16
#> 6     9    10
ecfdbz9o

ecfdbz9o2#

如果某人更喜欢{purrr}选项:

imap(res, ~dplyr::copy_to(dest = my_db, 
                            df = .x,
                            name = .y,
                            overwrite = TRUE))

imap(res, ~dbWriteTable(conn = my_db, .y,
                                        value = .x,
                                       overwrite = TRUE))

相关问题