#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 = '_')