首页 > 解决方案 > 用 dbplyr 总结的五位数

问题描述

我有 4 年使用 R 的经验,但我对大数据游戏非常陌生,因为我一直在处理 csv 文件。

从远处操纵大量数据令人兴奋,但也不知何故令人沮丧,因为您习惯于重新设计一些简单的事情。

我现在正在努力的任务是对变量进行基本的 5 位数摘要:

summary(df$X)

在某些情况下,我与 impala 有关,这些代码行工作正常:

library(dbplyr)
localTable <- tbl(con, 'serverTable')
localTable %>% tally()
localTable %>% filter(X > 10) %>% tally()

如果我只是写

localTable

相反,RStudio 卡住/需要很多时间,所以我用任务管理器抑制它。

回到我当前的问题,我尝试通过以下方式进行 5 位数的摘要:

summary(localTable$X) #returns Length 0, Class NULL, Mode NULL
localTable %>% fivenum(X) #returns Error in rank(x, ties.method = "min", na.last = "keep") : unimplemented type 'list' in 'greater'

还使用summary构建自定义summary()

localTable %>% summarize(Min = min(X),
         Q1 = quantile(X, .25),
         Avg = mean(X), 
         Q3 = quantile(X, .75),
         Max = max(X))

给我一个语法错误。

我的猜测是,我的代码和服务器之间以数据结构的形式存在一个非常微不足道的缺失链接,但我无法弄清楚是什么。

我也尝试将 localTable$x 保存到内存变量中

XL <- localTable$X

但我总是得到一个 NULL

在图形方面,如果我尝试使用 dbplot

library(dbplot)
localTable %>% dbplot_histogram(X)

我得到一个空的图形。

我考虑过利用 boxplot 函数中的 5 位数摘要,可以这么说,ggplotbuild(object)$data,但是使用 dbplot_boxplot 我得到错误找不到函数“dbplot_boxplot”。

我开始使用 dbplyr,因为我对 dplyr 非常熟悉,并且我不想使用 DBI::dbGetQuery 在 SQL 中编写查询,但是您可以建议其他软件包,例如 implyR、sparklyR 等,以及有关该主题的教程很大,因为我发现的那些是非常基本的。

编辑:

根据评论中的要求,我添加了结果

str(localTable)

这是

    List of 2 
$ src:List of 2
      ..$ con  :Formal class 'Impala' [package ".GlobalEnv"] with 4 slots
      .. .. ..@ ptr     :<externalptr> 
      .. .. ..@ quote   : chr "`"
      .. .. ..@ info    :List of 15
      .. .. .. ..$ dbname                       : chr "IMPALA"
      .. .. .. ..$ dbms.name                    : chr "Impala"
      .. .. .. ..$ db.version                   : chr "2.9.0-cdh5.12.1"
      .. .. .. ..$ username                     : chr "User"
      .. .. .. ..$ host                         : chr ""
      .. .. .. ..$ port                         : chr ""
      .. .. .. ..$ sourcename                   : chr "impala connector"
      .. .. .. ..$ servername                   : chr "Impala"
      .. .. .. ..$ drivername                   : chr "Cloudera ODBC Driver for Impala"
      .. .. .. ..$ odbc.version                 : chr "03.80.0000"
      .. .. .. ..$ driver.version               : chr "2.6.11.1011"
      .. .. .. ..$ odbcdriver.version           : chr "03.80"
      .. .. .. ..$ supports.transactions        : logi FALSE
      .. .. .. ..$ getdata.extensions.any_column: logi TRUE
      .. .. .. ..$ getdata.extensions.any_order : logi TRUE
      .. .. .. ..- attr(*, "class")= chr [1:3] "Impala" "driver_info" "list"
      .. .. ..@ encoding: chr ""
      ..$ disco: NULL
      ..- attr(*, "class")= chr [1:4] "src_Impala" "src_dbi" "src_sql" "src"
     $ ops:List of 2
      ..$ x   : 'ident' chr "serverTable"
      ..$ vars: chr [1:157] "X" ...
      ..- attr(*, "class")= chr [1:3] "op_base_remote" "op_base" "op"
     - attr(*, "class")= chr [1:5] "tbl_Impala" "tbl_dbi" "tbl_sql" "tbl_lazy" ...

不确定我是否可以输入我的表格,因为它是敏感信息

标签: rimpalasummarydbplyr

解决方案


你的帖子有很多方面。我将尝试解决主要问题。

(1)你打电话localTable的不是本地的。您拥有的是远程表的本地访问点。它是一个远程表,因为数据存储在数据库中,而不是 R 中。

要将远程表复制到本地 R 内存中,请使用localTable = collect(remoteTable). 小心使用它。如果数据库中的表有很多 GB,那么传输到 R 的速度会很慢。此外,如果您collect的数据库表大于 R 可用的 ram,那么您将收到内存不足错误。

我建议使用collectfor 将汇总结果移动到 R 中。在数据库中进行处理和汇总,然后将结果提取到 R 中。或者,使用remoteTable %>% head(20) %>% collect()将前 20 行复制到 R 中。

(2)tableName$colname不适用于远程表。在 R 中,$符号允许您访问列表的命名组件。Data.frames 是一种特殊的列表。如果您尝试data(iris)跟随names(iris)您将获得 iris 的列名。其中任何一个都可以使用iris$.

但是,正如您所str(localTable)展示的,localTable是一个长度为 2 的列表,其中第一个命名为 item src。如果你打电话names(localTable),你会收到两个名字,第一个是src。这意味着您可以调用localTable$src(您也可以调用localTable$src列表localTable$src$con)。

使用 dbplyr 时,R 将数据操作命令转换为数据库语言。为大多数 dplyr 命令定义了翻译,但没有为所有 R 命令定义翻译。

因此,仅访问特定列的推荐方法是使用selectdplyr:

local_copy_of_just_one_column = remoteTable %>%
  select(required_column) %>%
  collect()

(3)您拥有使用自定义摘要功能的正确方法。这是在不将数据拉入本地内存 (RAM) 的情况下生成五位数摘要的最佳方法。

语法错误的一个可能原因是您可能使用了没有翻译成数据库语言的 R 命令。

您可以检查命令是否具有使用定义的翻译translate_sql。我建议你试试

library(dbplyr)
translate_sql(quantile(colname, 0.25))

看看翻译的样子。

您可以使用 . 查看整个表操作的翻译show_query。这是我调试 SQL 翻译时的首选方法。尝试:

localTable %>%
  summarize(Min = min(X),
            Q1 = quantile(X, .25),
            Avg = mean(X), 
            Q3 = quantile(X, .75),
            Max = max(X)) %>%
  show_query()

如果这不会产生有效的 SQL,则执行该命令将出错。

一个可能的原因是MinMax在 SQL 中具有特殊含义,因此可能会在您的翻译中产生奇怪的行为。

当我尝试使用它时,quantile它看起来可能需要OVERSQL 中的子句。这是使用创建的group_by。因此,也许您想要以下内容:

localSummary = remoteTable %>%
  # create dummy column
  mutate(ones = 1) %>%
  # group to satisfy over clause
  group_by(ones) %>%
  summarise(var_min = min(var),
            var_lq = quantile(var, 0.25),
            var_mean = mean(var),
            var_uq = quantile(var, 0.75),
            var_max = max(var)) %>%
  # copy results from database into R memory
  collect()

推荐阅读