代码之家  ›  专栏  ›  技术社区  ›  Farzad

错误rsqlite\U fetch in R

  •  0
  • Farzad  · 技术社区  · 7 年前

    我有一个“CSV”格式的数据集,包含28个变量和7400个观察值。我在R中导入了名为“films”的数据集,我想清除它。通过这种方式,我使用了“sqldf”和“SQLite”库。但当我使用“sqldf”时,我收到警告,因此我的数据集也不会更新:

    enter image description here

    color   director_name   num_critic_for_reviews  duration
    Color   James Cameron   723                       178
    Color   Gore Verbinski  302                       169
    Color   Sam Mendes      602                       148
    

    我使用的代码如下:

    library(RSQLite) 
    library(sqldf)
    db <- dbConnect(SQLite(), "tempdb")  
    
    dbWriteTable(db,"films",films, overwrite=TRUE)
    
    d <- sqldf(c('update films set movie_title=lower(movie_title)', 'select * from films'))
    d <- sqldf(c('update films set actor_3_name=lower(actor_3_name)', 'select * from films'))
    d <- sqldf(c('update films set actor_2_name=lower(actor_2_name)', 'select * from films'))
    d <- sqldf(c('update films set actor_1_name=lower(actor_1_name)', 'select * from films'))
    d <- sqldf(c('update films set director_name=lower(director_name)', 'select * from films'))
    
    
    # Warning message:
    # In rsqlite_fetch(res@ptr, n = n) :
    #   Don't need to call dbFetch() for statements, only for queries
    

    有什么问题?

    1 回复  |  直到 7 年前
        1
  •  3
  •   r2evans    7 年前

    这里有几个问题。

    第一 :

    # 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 诸如此类。

    1. 您正在创建 db 直接SQL查询的句柄(不是 sqldf ),但你从不使用它。正如您稍后将看到的,(a)使用 dbExecute (和相关功能) 数据库 手柄,或(b)使用 sqldf ,无需 dbConnect 还有朋友。

    2. 使用时 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)
      
    3. 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'))
      
    4. 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'))
      
    5. 你真的需要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)
      })