Как соединить векторы с разной длиной в одну матрицу

У меня есть кадр данных, как это:

    id                 class  
   146                H02J
   146                F03D
   146                F03D
   287                F16F
   287                F16F
  1040                F03D
  1040                F16D
  1040                F03D
  1042                F03D
  1042                G01W
  1042                F03D
  1042                F03D
  1042                F03D
  1816                G06F
  1816                H04Q
  1816                H04L
  1816                H04W

Теперь я хочу построить векторы с числовыми значениями, каждый из которых представляет одно приложение, а каждое числовое значение представляет class,

Из-за разной длины векторов я не могу определить матрицу с векторами, с моими навыками R, и я благодарен за идеи для решения этой проблемы.

Выходными данными должна быть матрица, подобная этой, с целью определения расстояния между векторами.

> mat
     [,1] [,2] [,3] [,4] [,5]
[1,]    6    1    1   NA   NA
[2,]    3    3   NA   NA   NA
[3,]    1    2    1   NA   NA
[4,]    1    4    1    1    1
[5,]    5    8    7    9   NA

Я получил это с:

v1 <- subset(num, id==146)
v2 <- subset(num, id==287)
v3 <- subset(num, id==1040)
v4 <- subset(num, id==1042)
v5 <- subset(num, id==1816)

list <- list(c(v1), c(v2), c(v3), c(v4), c(v5))
list
max.length <- max(sapply(list, length))
list <- lapply(list, function(x) { c(x, rep(NA, max.length-length(x)))})
do.call(rbind, list)
mat <- do.call(rbind, list)

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

3 ответа

Решение

Ты можешь использовать rbind.fill.matrix от plyr пакет:

library(plyr)
do.call(rbind.fill.matrix,  tapply(as.integer(num$class), num$id, t))

Результат:

     1 2  3  4  5
[1,] 6 1  1 NA NA
[2,] 3 3 NA NA NA
[3,] 1 2  1 NA NA
[4,] 1 4  1  1  1
[5,] 5 8  7  9 NA

С dplyr а также tidyr пакеты, вы можете сделать:

library(dplyr)
library(tidyr)

d %>% 
  group_by(id) %>% 
  mutate(i=1:n(),value=as.integer(class),class=NULL) %>% 
  spread(i,value)

#     id 1 2  3  4  5
# 1  146 6 1  1 NA NA
# 2  287 3 3 NA NA NA
# 3 1040 1 2  1 NA NA
# 4 1042 1 4  1  1  1
# 5 1816 5 8  7  9 NA

где d это примерный набор данных:

d <- structure(list(id = c(146L, 146L, 146L, 287L, 287L, 1040L, 1040L, 
1040L, 1042L, 1042L, 1042L, 1042L, 1042L, 1816L, 1816L, 1816L, 
1816L), class = structure(c(6L, 1L, 1L, 3L, 3L, 1L, 2L, 1L, 1L, 
4L, 1L, 1L, 1L, 5L, 8L, 7L, 9L), .Label = c("F03D", "F16D", "F16F", 
"G01W", "G06F", "H02J", "H04L", "H04Q", "H04W"), class = "factor")), .Names = c("id", 
"class"), class = "data.frame", row.names = c(NA, -17L))

Вы можете использовать dcast функция от reshape2 пакет.

    library(reshape2)

    x <- dcast(num, id ~ class)

    mat <- as.matrix(x[,-1])

Обратите внимание, что имена столбцов для этой матрицы - это значения, найденные в столбце вашего класса. Кроме того, NA представлены как 0, которые больше подходят для вычисления расстояний.

Другие вопросы по тегам