Допустим, мы взяли данные mtcars и запустили PCA. Затем мы хотим узнать, какие марки автомобилей наиболее похожи в пространстве ПК, то есть ближайших соседей. Итак, кто-то провел анализ ближайших соседей и записал его.
Затем мне предоставляется фрейм данных, который выглядит следующим образом: фокусные автомобили указаны в столбце car, а первые и вторые ближайшие соседи n1 и n2 перечислены в своих столбцах.
tibble(car = c("Honda", "Toyota", "Mazda", "Fiat", "Lotus"),
nn1 = c("Toyota", "Honda", "Toyota", "Lotus", "Mazda"),
nn2 = c("Mazda", "Mazda", "Honda", "Honda", "Fiat"))
# A tibble: 5 × 3
car nn1 nn2
<chr> <chr> <chr>
1 Honda Toyota Mazda
2 Toyota Honda Mazda
3 Mazda Toyota Honda
4 Fiat Lotus Honda
5 Lotus Mazda Fiat
Я хотел бы преобразовать это в фрейм данных одноразового стиля, где 5 основных марок автомобилей являются строками, а столбцы - возможными соседями, каждый из которых закодирован 0 или 1 в зависимости от того, был ли он одним из ближайших соседей. к фокусному автомобилю. В виде тиббла это будет выглядеть так:
# A tibble: 5 × 6
cars Honda Toyota Mazda Fiat Lotus
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Honda 0 1 1 0 0
2 Toyota 1 0 1 0 0
3 Mazda 1 1 0 0 0
4 Fiat 1 0 0 0 1
5 Lotus 0 0 1 1 0
или это может быть такой фрейм данных:
Honda Toyota Mazda Fiat Lotus
Honda 0 1 1 0 0
Toyota 1 0 1 0 0
Mazda 1 1 0 0 0
Fiat 1 0 0 0 1
Lotus 0 0 1 1 0





Больше похоже на матрицу смежности, чем на матрицу горячего кодирования. Звоню на ваши данные df:
library(tidyr)
library(dplyr)
df |>
pivot_longer(-car) |>
mutate(fill = 1) |>
pivot_wider(id_cols = car, names_from = value, values_from = fill, values_fill = 0)
# # A tibble: 5 × 6
# car Toyota Mazda Honda Lotus Fiat
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 Honda 1 1 0 0 0
# 2 Toyota 0 1 1 0 0
# 3 Mazda 1 0 1 0 0
# 4 Fiat 0 0 1 1 0
# 5 Lotus 0 1 0 0 1
Может быть, вы можете попробовать table, как показано ниже
> with(df, table(rep(car, each = ncol(df) - 1), t(df[-1])))
Fiat Honda Lotus Mazda Toyota
Fiat 0 1 1 0 0
Honda 0 0 0 1 1
Lotus 1 0 0 1 0
Mazda 0 1 0 0 1
Toyota 0 1 0 1 0
или
> with(df, table(data.frame(x = car, y = c(nn1, nn2))))
y
x Fiat Honda Lotus Mazda Toyota
Fiat 0 1 1 0 0
Honda 0 0 0 1 1
Lotus 1 0 0 1 0
Mazda 0 1 0 0 1
Toyota 0 1 0 1 0
или как @thelatemail предложил в комментарии
> table(cbind(df[1], unlist(df[-1])))
unlist(df[-1])
car Fiat Honda Lotus Mazda Toyota
Fiat 0 1 1 0 0
Honda 0 0 0 1 1
Lotus 1 0 0 1 0
Mazda 0 1 0 0 1
Toyota 0 1 0 1 0
Вариация на тему table(cbind(df[1], unlist(df[-1]))) или table(cbind(df[1], neighbour=unlist(df[-1]))), если хотите красивые названия.
@thelatemail, если вы опубликуете это, я знаю, что поддержу.
@thelatemail да, спасибо за ваш вклад, он кажется более кратким :)
as.data.frame.matrix(table(reshape2::melt(df, id = 1)[-2]))
#> Fiat Honda Lotus Mazda Toyota
#> Fiat 0 1 1 0 0
#> Honda 0 0 0 1 1
#> Lotus 1 0 0 1 0
#> Mazda 0 1 0 0 1
#> Toyota 0 1 0 1 0
Из пакета fastDummies функция dummy_cols() создаст эти столбцы, если вы сначала объедините их:
library(fastDummies)
library(tidyr)
df |>
unite("dummy", starts_with("nn"), remove = F) |>
dummy_cols("dummy", split = "_", omit_colname_prefix = T, remove_selected_columns = T)
Выход
car nn1 nn2 Honda Mazda Lotus Fiat Toyota
<chr> <chr> <chr> <int> <int> <int> <int> <int>
1 Honda Toyota Mazda 0 1 0 0 1
2 Toyota Honda Mazda 1 1 0 0 0
3 Mazda Toyota Honda 1 0 0 0 1
4 Fiat Lotus Honda 1 0 1 0 0
5 Lotus Mazda Fiat 0 1 0 1 0
матрица смежности для меня новая, спасибо за четкий ответ!