создание новых столбцов Tibble на основе сопоставления плюс пользовательские данные - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь сгенерировать новые столбцы в таблице из результатов функции, которая принимает в качестве входных данных несколько существующих столбцов этой таблицы плюс пользовательские данные. В качестве упрощенного примера я хотел бы использовать эту функцию

addup <- function(x, y, z){x + y + z}

и используйте его для добавления чисел в существующие столбцы в этой таблице ...

set.seed(1)
(tib <- tibble(num1 = sample(12), num2 = sample(12)))
# A tibble: 12 x 2
    num1  num2
   <int> <int>
 1     8     5
 2     6     3
 3     7     7
 4     3    11
 5     1     2
 6     2     1
 7    11     6
 8    10     9
 9     4     8
10     9    12
11     5    10
12    12     4

... вместе с пользовательским вводом. Например, если пользователь определяет вектор

vec <- c(3,6,4)

Я хотел бы создать один новый столбец для элемента в vec, добавив сопоставленные значения с пользовательскими значениями ввода.

В этом случае желаемый результат будет выглядеть примерно так:

# A tibble: 12 x 5
    num1  num2   `3`   `6`   `4`
   <int> <int> <dbl> <dbl> <dbl>
 1     5     7    15    18    16
 2     8     2    13    16    14
 3     7     9    19    22    20
 4     1    11    15    18    16
 5     3     3     9    12    10
 6     9    12    24    27    25
 7     6     6    15    18    16
 8    10    10    23    26    24
 9    11     4    18    21    19
10    12     5    20    23    21
11     4     1     8    11     9
12     2     8    13    16    14

Если бы я знал vec заранее, я мог бы достичь этого с помощью

tib %>% 
  mutate("3" = map2_dbl(num1, num2, ~addup(.x, .y, 3)),
         "6" = map2_dbl(num1, num2, ~addup(.x, .y, 6)), 
         "4" = map2_dbl(num1, num2, ~addup(.x, .y, 4))) 

но так как длина vec может варьироваться, я не знаю, как это обобщить. Я нашел этот ответ повторное изменение в tidyverse , но там функции повторяются над существующими столбцами вместо использования нескольких существующих столбцов для сопоставления.

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 17 января 2019

При этом используется lapply, чтобы применить функцию к каждому элементу вашего вектора, затем привязать результат к исходному фрейму данных и добавить имена столбцов.

# Given example
set.seed(1)
(tib <- tibble(num1 = sample(12), num2 = sample(12)))
addup <- function(x, y, z){x + y + z}
vec <- c(3,6,4)

# Add columns and bind to original data frame
foo <- cbind(tib, lapply(vec, function(x)addup(tib$num1, tib$num2, x)))

# Correct column names
colnames(foo)[(ncol(tib)+1):ncol(foo)] <- vec

# Print result
print(foo)

#    num1 num2  3  6  4
# 1     4    9 16 19 17
# 2     5    5 13 16 14
# 3     6    8 17 20 18
# 4     9   11 23 26 24
# 5     2    6 11 14 12
# 6     7    7 17 20 18
# 7    10    3 16 19 17
# 8    12    4 19 22 20
# 9     3   12 18 21 19
# 10    1    1  5  8  6
# 11   11    2 16 19 17
# 12    8   10 21 24 22
0 голосов
/ 17 января 2019

Поскольку нам не нужно использовать функцию или имена в качестве аргументов, это относительно просто. Вам просто нужно перебрать vec с помощью функции, которая возвращает итоговый столбец, а затем объединить с исходной таблицей. Если у вас есть функция addup, которая принимает векторные входы, то вы можете пропустить всю часть map2; на самом деле это так, но я не знаю, выполняет ли ваша настоящая функция.

library(tidyverse)
vec <- c(3,6,4)
set.seed(1)
tib <- tibble(num1 = sample(12), num2 = sample(12))

addup <- function(c1, c2, z) {c1 + c2 + z}
addup_vec <- function(df, vec) {
  new_cols <- map_dfc(
    .x = vec,
    .f = function(v) {
      map2_dbl(
        .x = df[["num1"]],
        .y = df[["num2"]],
        .f = ~ addup(.x, .y, v)
      )
    }
  )
  colnames(new_cols) <- vec
  bind_cols(df, new_cols)
}

tib %>%
  addup_vec(vec)
#> # A tibble: 12 x 5
#>     num1  num2   `3`   `6`   `4`
#>    <int> <int> <dbl> <dbl> <dbl>
#>  1     4     9    16    19    17
#>  2     5     5    13    16    14
#>  3     6     8    17    20    18
#>  4     9    11    23    26    24
#>  5     2     6    11    14    12
#>  6     7     7    17    20    18
#>  7    10     3    16    19    17
#>  8    12     4    19    22    20
#>  9     3    12    18    21    19
#> 10     1     1     5     8     6
#> 11    11     2    16    19    17
#> 12     8    10    21    24    22

Создано в 2019-01-16 с помощью пакета Представить (v0.2.0).

...