2016-08-13 11 views
0

Рассмотрим data.frame, состоящий из двух переменных идентификаторов и третьей переменной, relate, показывающим соотношение (например, ковариации) между каждой парой ID переменных:Expand unblanced data.frame значений двух переменных, относящихся к ID сбалансированной матрице

options(stringsAsFactors = FALSE, digits = 2) 
set.seed(1) 
(example <- data.frame(v1 = LETTERS[rep(c(2,3,1,4,7), 
             times = c(3,2,2,1,2))], 
         v2 = LETTERS[c(2:4, 4:5, 4:5, 5,8,9)], 
         relate = rnorm(10))) 

    v1 v2 relate 
1 B B -0.63 
2 B C 0.18 
3 B D -0.84 
4 C D 1.60 
5 C E 0.33 
6 A D -0.82 
7 A E 0.49 
8 D E 0.74 
9 G H 0.58 
10 G I -0.31 

Эти данные являются неуравновешенными тем, что не каждое попарное отношение учитывается, и не каждый в v1 находится в v2 и наоборот.

Цель состоит в том, чтобы расширить эти данные в симметричную матрицу, где все уникальные значения в обоих v1 и v2 содержат имена строк и столбцов, и записей являются соответствующими значениями relate (если она существует, то NA). Другими словами, чтобы заполнить приведенную ниже матрицу со значениями relate:

vars <- with(example, unique(c(v1, v2))) 
matrix(nrow = length(vars), 
     ncol = length(vars), 
     dimnames = list(vars, vars)) 
    B C A D G E H I 
B NA NA NA NA NA NA NA NA 
C NA NA NA NA NA NA NA NA 
A NA NA NA NA NA NA NA NA 
D NA NA NA NA NA NA NA NA 
G NA NA NA NA NA NA NA NA 
E NA NA NA NA NA NA NA NA 
H NA NA NA NA NA NA NA NA 
I NA NA NA NA NA NA NA NA 

Однако готовых решений я пытался до сих пор (data.table::dcast, reshape2:dcast) производят следующие неуравновешенных результаты:

data.table::dcast(example, v1~v2, value.var = 'relate') 
    v1  B C  D E H  I 
1 A NA NA -0.82 0.49 NA NA 
2 B -0.63 0.18 -0.84 NA NA NA 
3 C NA NA 1.60 0.33 NA NA 
4 D NA NA NA 0.74 NA NA 
5 G NA NA NA NA 0.58 -0.31 

есть ли эффективный способ вместо того, чтобы получить сбалансированную , симметричного матрицы значений из набора ID-пар и связанные ценности?

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

+3

Так как вы уже выделили «матрицу» -сайт 'mat'-, вы можете использовать' mat [as.matrix (пример [1: 2])] = пример $ relate' –

+0

@alexis_laz очень элегантный - забота о расширении на ответ? –

+0

Связанный: http://stackoverflow.com/questions/9617348/reshape-three-column-data-frame-to-matrix-long-to-wide-format – Frank

ответ

2

Мы можем преобразовать 'v1/v2' столбцы factor с levels, указанной в качестве unique элементов в unlist ред 'v1/v2' столбцы в 'примере', а затем сделать dcast с drop=FALSE

library(data.table) 
un1 <- unique(unlist(example[1:2])) 
setDT(example)[, paste0("v", 1:2) := lapply(.SD, factor, levels = un1), 
      .SDcols = v1:v2] 
dcast(example, v1~v2, value.var = "relate", drop = FALSE) 
# v1  B C A  D G E H  I 
#1: B -0.63 0.18 NA -0.84 NA NA NA NA 
#2: C NA NA NA 1.60 NA 0.33 NA NA 
#3: A NA NA NA -0.82 NA 0.49 NA NA 
#4: D NA NA NA NA NA 0.74 NA NA 
#5: G NA NA NA NA NA NA 0.58 -0.31 
#6: E NA NA NA NA NA NA NA NA 
#7: H NA NA NA NA NA NA NA NA 
#8: I NA NA NA NA NA NA NA NA 
+1

Именно то, что я искал, - попробовал указать «drop = FALSE', но не указывалось дополнительных уровней факторов. Приветствия. –