Получить сводку () mytable из базы данных SQL с R без записи в мой сеанс R - PullRequest
1 голос
/ 09 марта 2020

Я хочу получить таблицу из SQL базы данных с R, я могу это сделать,

df <- sqlQuery(channel, "select * from scheme.mytable1")

Но затем я хочу получить функцию сводной таблицы ( Я хочу увидеть сводку таблиц)

summary(df)

Я могу сделать это, подключившись к SQL db и перенеся таблицу в мой сеанс R (см. Его как таблицу в R консоль как df), а затем получите сводку (df)

Но я хочу увидеть ее сводку БЕЗ записи в мою сессию R, потому что таблица слишком большая. (миллион столбцов) Я не могу записать это в мой сеанс R.

Но я хочу видеть только сводку по его столбцам.

summary(sqlQuery(channel, "select * from scheme.mytable1"))

Я хочу сделать что-то подобное выше (но код не работает, просто чтобы покажи свою цель)

Как я могу это сделать? любой пакет? любая функция? Развертыватель?

Спасибо!

1 Ответ

1 голос
/ 10 марта 2020

Одна вещь, которую вы могли бы сделать, это использовать dplyr::tbl для создания удаленной таблицы из источника данных и написать свой собственный метод summary, который выполняет большую часть вычислений в БД. Вот как это может выглядеть:

library(dplyr)
library(tidyr)

# create a connection to table using dplyr, use dummy data 
# in memory SQLite here,in practice would do df <- tbl(con,  "mytable1")
con <- DBI::dbConnect(RSQLite::SQLite(), dbname = ":memory:")
copy_to(con, ggplot2::diamonds, "diamonds")
diamonds_db <- tbl(con,  "diamonds")

# create custom summary method for the connection
summary.tbl_SQLiteConnection <- function(object, ...) {
  suppressMessages({
    nums <- object %>% 
      summarise_if(
        is.numeric, 
        # can put whatever functions here
        # these should work for most DBs
        list(Min = min, Max = max, Mean = mean)
      ) %>% 
      collect() %>% 
      pivot_longer(everything()) %>% 
      mutate(name = stringi::stri_reverse(name)) %>% 
      separate(name, into = c("fun", "var"), sep = "_", extra = "merge") %>% 
      mutate_at(vars(var, fun), stringi::stri_reverse) %>% 
      mutate(val = paste0(fun, ": ", round(value, 2))) %>% 
      split(.$var) %>% 
      lapply(`[[`, "val")
    other_nms <- object %>% 
      select_if(~!is.numeric(.x)) %>% 
      head(1) %>% 
      collect() %>% 
      names()
    other <- lapply(other_nms, function(x) {
      x <- ensym(x)
      object %>% 
        group_by(!!x) %>% 
        tally() %>%
        arrange(desc(n)) %>%
        # only show top 10 values
        head(10) %>%
        collect() %>% 
        mutate(tmp = paste0(!!x, ": ", n)) %>% 
        pull(tmp)
    })
  })
  names(other) <- other_nms
  lst <- c(other, nums)
  # format similar to summary.data.frame 
  mat <- matrix(NA_character_, max(sapply(lst, length)), length(lst))
  for (i in seq_along(lst)) {
    for (j in seq_along(mat[, i])) {
      mat[j, i] <- lst[[i]][j]
    }
  }
  colnames(mat) <- names(lst)
  rownames(mat) <- rep("", dim(mat)[1])
  structure(mat, class = "table")
}

summary(diamonds_db)
#> cut              color    clarity    carat     depth       price        table       x          y          z         
#> Fair: 1610       D: 6775  I1: 741    Min: 0.2  Min: 43     Min: 326     Min: 43     Min: 0     Min: 0     Min: 0    
#> Good: 4906       E: 9797  IF: 1790   Max: 5.01 Max: 79     Max: 18823   Max: 95     Max: 10.74 Max: 58.9  Max: 31.8 
#> Ideal: 21551     F: 9542  SI1: 13065 Mean: 0.8 Mean: 61.75 Mean: 3932.8 Mean: 57.46 Mean: 5.73 Mean: 5.73 Mean: 3.54
#> Premium: 13791   G: 11292 SI2: 9194                                                                                 
#> Very Good: 12082 H: 8304  VS1: 8171                                                                                 
#>                  I: 5422  VS2: 12258                                                                                
#>                  J: 2808  VVS1: 3655                                                                                
#>                           VVS2: 5066 

Я пробовал это на слишком большом столе, чтобы поместиться в памяти, и это сработало. Эта функция не точно соответствует тому, что дано summary.data.frame, но должна быть началом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...