Как наложить два кадра данных с одинаковыми размерами, вставляя значения в соответствующие ячейки?

#r #dataframe #dplyr #merge

Вопрос:

Есть ли простой способ объединить tidyr::unite() и dplyr::merge() , когда у нас есть два фрейма данных с одинаковой структурой?

Пример

1 — Очень простой сценарий

Скажем, у нас есть два кадра данных, которые мы хотим объединить/объединить/»наложить»:

 df_1 <- 
  data.frame(
    first_name = c("john", "rachel", "thomas", "rebecca")
  )


df_2 <-
  data.frame(
    last_name = c("smith", "williams", "miller", "jones")
  )
 

Тогда я бы сделал:

 cbind(df_1, df_2) %>%
  tidyr::unite(full, first_name, last_name)
#>              full
#> 1      john_smith
#> 2 rachel_williams
#> 3   thomas_miller
#> 4   rebecca_jones
 

2 — Более сложный сценарий

У нас может быть более богатый набор данных, чем те, которые показаны выше. Возьмем, к примеру my_mtcars (как показано ниже), что мы хотим «объединить-объединить-наложить» с другим фреймом данных, таким как df_random_vals (см. Ниже).

 # my_mtcars

library(tibble)

my_mtcars <- 
  mtcars %>%
  rownames_to_column("cars") %>%
  as_tibble()

my_mtcars
#> # A tibble: 32 x 12
#>    cars          mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <chr>       <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1 Mazda RX4    21       6  160    110  3.9   2.62  16.5     0     1     4     4
#>  2 Mazda RX4 ~  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#>  3 Datsun 710   22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#>  4 Hornet 4 D~  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#>  5 Hornet Spo~  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#>  6 Valiant      18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#>  7 Duster 360   14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  8 Merc 240D    24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#>  9 Merc 230     22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 10 Merc 280     19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # ... with 22 more rows
 

Создано 2021-07-27 пакетом reprex (v2.0.0)

The df_random_vals table is going to be in the same dimensions as my_mtcars .

 
dim_my_mtcars <- dim(my_mtcars)
target_nrows  <- dim_my_mtcars[1]
target_ncols  <- dim_my_mtcars[2]

set.seed(2021)

my_mat <-
  matrix(data = rnorm(target_nrows*target_ncols), 
       ncol = target_ncols, 
       nrow = target_nrows) 

df_random_vals <-
  my_mat %>%
  as.data.frame() %>%
  as_tibble()

df_random_vals
#> # A tibble: 32 x 12
#>         V1      V2      V3      V4     V5     V6     V7      V8      V9    V10
#>      <dbl>   <dbl>   <dbl>   <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>  <dbl>
#>  1 -0.122   1.02    0.231  -0.647   1.02   0.828  1.22   1.92    0.850  -1.99 
#>  2  0.552  -1.42   -0.984  -0.868   2.45   0.355 -0.561 -0.237  -1.53   -1.49 
#>  3  0.349  -0.605   0.565  -0.509  -0.246  0.159  0.337  1.57   -0.0316  0.255
#>  4  0.360  -1.58    1.62   -2.08    0.542  0.955 -1.54   0.481   1.43   -0.814
#>  5  0.898  -1.29   -0.252  -0.260   0.197 -0.340 -0.240  0.0426 -0.927   0.834
#>  6 -1.92   -1.45   -1.06    0.450  -2.07  -0.727  0.515  0.440   1.01   -1.15 
#>  7  0.262  -0.0871 -0.348  -0.143   0.513 -1.70  -0.239 -1.88   -0.0860 -0.140
#>  8  0.916   0.505  -0.0430 -0.487  -0.406  1.95   0.582 -1.72    0.938   1.18 
#>  9  0.0138  0.116  -1.40   -1.20    0.356  2.67   0.270  1.88   -0.518   0.187
#> 10  1.73    1.76    1.49    0.0469 -0.332  2.06  -1.34  -0.0313 -0.935  -0.695
#> # ... with 22 more rows, and 2 more variables: V11 <dbl>, V12 <dbl>

identical(
  dim(df_random_vals), 
  dim(my_mtcars)
)
#> [1] TRUE
 

Мой вопрос.
Учитывая, что оба my_mtcars и df_random_vals имеют одинаковые размеры , как мы можем «наложить» df_random_vals друг на my_mtcars друга, чтобы получить следующий желаемый результат:

 # A tibble: 32 x 12
   cars                    mpg         cyl      disp         hp         drat        wt           qsec         vs       am       gear     carb    
   <chr>                   <chr>       <chr>    <chr>        <chr>      <chr>       <chr>        <chr>        <chr>    <chr>    <chr>    <chr>   
 1 Mazda RX4_-0.122        21_1.019    6_0.231  160_-0.647   110_1.015  3.9_0.828   2.62_1.219   16.46_1.917  0_0.85   1_-1.988 4_0.4    4_0.935 
 2 Mazda RX4 Wag_0.552     21_-1.421   6_-0.984 160_-0.868   110_2.454  3.9_0.355   2.875_-0.561 17.02_-0.237 0_-1.531 1_-1.492 4_0.748  4_-0.012
 3 Datsun 710_0.349        22.8_-0.605 4_0.565  108_-0.509   93_-0.246  3.85_0.159  2.32_0.337   18.61_1.572  1_-0.032 1_0.255  4_-0.088 1_0.26  
 4 Hornet 4 Drive_0.36     21.4_-1.583 6_1.617  258_-2.078   110_0.542  3.08_0.955  3.215_-1.537 19.44_0.481  1_1.428  0_-0.814 3_-1.086 1_1.151 
 5 Hornet Sportabout_0.898 18.7_-1.286 8_-0.252 360_-0.26    175_0.197  3.15_-0.34  3.44_-0.24   17.02_0.043  0_-0.927 0_0.834  3_-0.085 2_1.168 
 6 Valiant_-1.923          18.1_-1.455 6_-1.056 225_0.45     105_-2.071 2.76_-0.727 3.46_0.515   20.22_0.44   1_1.006  0_-1.152 3_0.466  1_-1.188
 7 Duster 360_0.262        14.3_-0.087 8_-0.348 360_-0.143   245_0.513  3.21_-1.698 3.57_-0.239  15.84_-1.881 0_-0.086 0_-0.14  3_0      4_0.221 
 8 Merc 240D_0.916         24.4_0.505  4_-0.043 146.7_-0.487 62_-0.406  3.69_1.954  3.19_0.582   20_-1.724    1_0.938  0_1.176  4_0.616  2_1.134 
 9 Merc 230_0.014          22.8_0.116  4_-1.398 140.8_-1.196 95_0.356   3.92_2.667  3.15_0.27    22.9_1.883   1_-0.518 0_0.187  4_-0.652 2_0.511 
10 Merc 280_1.73           19.2_1.76   6_1.49   167.6_0.047  123_-0.332 3.92_2.063  3.44_-1.343  18.3_-0.031  1_-0.935 0_-0.695 4_0.447  4_-1.497
# ... with 22 more rows
 

Обратите внимание , как каждое значение from df_random_vals вставляется в соответствующее значение from my_mtcars , как разделитель "_" .

Как может быть достигнуто такое «наложение», учитывая два кадра данных с одинаковыми размерами?

Ответ №1:

 library(purrr)

map2_dfc(my_mtcars, df_random_vals, paste, sep = "_") 
 

Комментарии:

1. святая корова, как просто!

Ответ №2:

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

 result <- data.frame(my_mtcars)
result[] <- paste(as.matrix(my_mtcars), as.matrix(df_random_vals), sep = '_')