Как я могу динамически создавать новые переменные / столбцы в базах данных в R, используя dplyr? - PullRequest
1 голос
/ 22 декабря 2019

Я новичок в Stackoverflow и довольно новичок в R. Я был бы очень признателен за вашу помощь.

Я использую функцию dplyr mutate() для создания набора новых столбцов на основе одного исходного столбца,Для априорно известного числа создаваемых столбцов все работает нормально.

Однако в моем приложении число создаваемых новых столбцов неизвестно (или скорее определяется как входной параметр перед запуском кода).

Для иллюстрации рассмотрим следующий минимальный рабочий пример:

library(RSQLite)
library(dplyr)
library(dbplyr)
library(DBI)

con <- DBI::dbConnect(RSQLite::SQLite(), path = ":memory:")

copy_to(con, mtcars, "mtcars", temporary = FALSE)

db <- tbl(con, "mtcars") %>%
    select(carb) %>%
    distinct(carb) %>%
    arrange(carb) %>%
    mutate(carb1 = carb + 1) %>%
    mutate(carb2 = carb + 2) %>%
    mutate(carb3 = carb + 3) %>%
    show_query() %>%
    collect()

В этом примере я создаю три новые переменные. Однако я хочу, чтобы программа работала с динамическим числом переменных (например, пять или десять новых переменных). Я также хотел бы выполнить все вычисления до collect(), потому что я хочу скопировать данные в память как можно позже.

Некоторые предыстории для моего реального приложения: я хочу использовать Функция DB2 ADD_MONTHS () . Поэтому мне нужно dplyr / dbplyr, чтобы сбросить эту функцию непосредственно в команду SQL. Поэтому мне нужно решение, которое на самом деле не использует логику фрейма данных - мне нужно, чтобы решение находилось в dplyr.

С другой точки зрения: в SAS я использовал бы макропроцессор для динамической сборки процессаSQL заявление. Есть ли эквивалент в R?

Ответы [ 2 ]

3 голосов
/ 22 декабря 2019

Мы можем использовать map

library(dplyr)
library(purrr)
library(stringr)
map_dfc(1:3, ~ df %>%
                  transmute(!! str_c('x', .x) := x + .x)) %>%
    bind_cols(df, .)
#  x x1 x2 x3
#1 1  2  3  4
#2 2  3  4  5
#3 3  4  5  6

В случае базы данных, выполните collect перед добавлением столбцов

dat <- tbl(con, "mtcars") %>%
        select(carb) %>%
        distinct(carb) %>%
        arrange(carb) %>%
        collect()
map_dfc(dat$carb, ~ dat %>%
                      transmute(!! str_c('carb', .x) := carb + .x)) %>%
    bind_cols(dat, .)
# A tibble: 6 x 7
#   carb carb1 carb2 carb3 carb4 carb6 carb8
#  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1     1     2     3     4     5     7     9
#2     2     3     4     5     6     8    10
#3     3     4     5     6     7     9    11
#4     4     5     6     7     8    10    12
#5     6     7     8     9    10    12    14
#6     8     9    10    11    12    14    16

Или другоевариант, если мы хотим сделать это до того, как collect ing передаст выражение в mutate

tbl(con, "mtcars") %>%
   select(carb) %>%
   distinct(carb) %>%
   arrange(carb) %>%
   mutate(!!! rlang::parse_exprs(str_c('carb', 1:3, sep="+", collapse=";"))) %>%
   rename_at(-1, ~ str_c('carb', 1:3)) %>%
   show_query() %>%
   collect()
#<SQL>
#SELECT `carb`, `carb` + 1.0 AS `carb1`, `carb` + 2.0 AS `carb2`, `carb` + 3.0 AS #`carb3`
#FROM (SELECT *
#FROM (SELECT DISTINCT *
#FROM (SELECT `carb`
#FROM `mtcars`))
#ORDER BY `carb`)
# A tibble: 6 x 4
#   carb carb1 carb2 carb3
#  <dbl> <dbl> <dbl> <dbl>
#1     1     2     3     4
#2     2     3     4     5
#3     3     4     5     6
#4     4     5     6     7
#5     6     7     8     9
#6     8     9    10    11
0 голосов
/ 22 декабря 2019

Мы можем использовать map2_dfc из purrr передать значения, чтобы добавить и добавить данные к оригиналу df.

library(dplyr)
library(purrr)

bind_cols(df, map2_dfc(1:3, df ,`+`))

#  x V1 V2 V3
#1 1  2  3  4
#2 2  3  4  5
#3 3  4  5  6
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...