sqlite 将多个文件从CSV读取到R中的DuckDB中,并使用新变量指示文件名中的年份

b09cbbtk  于 2022-11-15  发布在  SQLite
关注(0)|答案(2)|浏览(204)

我有几(8)个大文件(每个1M行),具有相同的变量/格式,按年单独保存。我想使用R中的duckdb数据库格式保存到单个表中。duck_read_csv()命令很好地实现了这一点。

问题:这种方法没有表示年的变量,因此丢失了重复测量的趋势。我的DBI和SQL知识有限,所以可能有一种简单的方法来做到这一点,但我被困在这里(下面是演示问题的简单示例):

library(duckdb)
con <- dbConnect(duckdb())

# example year 1 data
data <- data.frame(id = 1:3, b = letters[1:3]) # year = 1
path <- tempfile(fileext = ".csv")
write.csv(data, path, row.names = FALSE)

# example year 2 data
data2 <- data.frame(id = 1:3, b = letters[4:6]) # year = 2
path2 <- tempfile(fileext = ".csv")
write.csv(data2, path2, row.names = FALSE)

duckdb_read_csv(con, "data", files = c(path, path2)) # data is appended

这将产生以下结果--数据是按行追加的,但我需要一个变量来表示“年份”:

dbReadTable(con, "data")
  id b
1  1 a
2  2 b
3  3 c
4  1 d
5  2 e
6  3 f

有没有办法在这个过程中创建一个新的变量,或者更好的方法是为

yhxst69z

yhxst69z1#

一种方法是使用purrr::map_dfr+readr::read_csv进行读取,这允许您根据分配给文件路径的名称分配一个“id”列,然后将其注册为一个duckdb表:

library(dplyr)
purrr::map_dfr(c(year01 = path, 
                 year02 = path2),
               ~readr::read_csv(.x), 
               .id = "year") %>%
  duckdb_register(con, "data", .)

结果

tbl(con, "data") %>%
  collect()
# A tibble: 6 × 3
  year      id b    
  <chr>  <dbl> <chr>
1 year01     1 a    
2 year01     2 b    
3 year01     3 c    
4 year02     1 d    
5 year02     2 e    
6 year02     3 f
h9a6wy2h

h9a6wy2h2#

我修改了Jon的回答来解决我的问题(谢谢Jon)。文件太大,无法一次全部读取到内存中(每个文件大约2000万行),所以我每次迭代一个文件以传输到数据库(总共大约1.98亿行)。
我还使用gsub将文件名中的“年份”提取到一个单独的变量yrs中。

library(dplyr)
library(duckdb)
con <- dbConnect(duckdb())

# example year 1 data
data <- data.frame(id = 1:3, b = letters[1:3]) # year = 1
path1 <- tempfile(fileext = ".csv")
write.csv(data, path1, row.names = FALSE)

# example year 2 data
data2 <- data.frame(id = 1:3, b = letters[4:6]) # year = 2
path2 <- tempfile(fileext = ".csv")
write.csv(data2, path2, row.names = FALSE)

paths <- c(path1, path2)
yrs <- c("year1", "year2")

purrr::walk2(paths, yrs,
      ~{
        readr::read_csv(.x, n_max = Inf) %>% # read 1 file into memory at a time
          mutate(year = .y) %>% 
          rename_all(. %>% tolower()) %>%    # i really prefer lower case variable names
          duckdb::dbWriteTable(conn = con, name =  "data", value = .,  append =T) 
      })

相关问题