2017-10-04 1 views
5

J'ai du mal à faire de mes données.frame une matrice carrée. Maintenant, mes données ressemble à ceci:créer une matrice carrée à partir d'une trame de données

var1 var2 value 
    A B  4 
    C D  5 
    D A  2 
    B D  1 

Je suis en train de transformer la data.frame à une matrice qui ressemble à ceci:

A B C D 
    A 0 4 0 2 
    B 4 0 0 1 
    C 0 0 0 5 
    D 2 1 5 0 

J'ai essayé beaucoup de fonctions de différents package disponible dans R mais ne peut toujours pas trouver une solution.

+0

S'il vous plaît poster ces nombreuses fonctions que vous avez essayé et pourquoi cela n'a pas fonctionné – PoGibas

+1

'xtabs (valeur ~ var1 + var2, df)'? – Sotos

+1

@Sotos cette colonne manquerait 'C' – PoGibas

Répondre

3

Si nous faisons toutes les colonnes de caractères factor s avec les niveaux «A», «B», «C», «D», nous pouvons utiliser xtabs sans laisser tomber les colonnes.

Malheureusement, la matrice résultante n'est pas symétrique.

library('tidyverse') 

df <- tribble(
    ~var1, ~var2, ~value, 
    'A', 'B',  4, 
    'C', 'D',  5, 
    'D', 'A',  2, 
    'B', 'D',  1 
) 

df %>% 
    mutate_if(is.character, factor, levels=c('A', 'B', 'C', 'D')) %>% 
    xtabs(value ~ var1 + var2, ., drop.unused.levels = F) 
#  var2 
# var1 A B C D 
# A 0 4 0 0 
# B 0 0 0 1 
# C 0 0 0 5 
# D 2 0 0 0 

Pour le rendre symétrique, je viens d'ajouter sa transposition à elle-même. Cela ressemble à un peu d'un hack, cependant.

df %>% 
    mutate_if(is.character, factor, levels=c('A', 'B', 'C', 'D')) %>% 
    xtabs(value ~ var1 + var2, ., drop.unused.levels = F) %>% 
    '+'(., t(.)) 
#  var2 
# var1 A B C D 
# A 0 4 0 2 
# B 4 0 0 1 
# C 0 0 0 5 
# D 2 1 5 0 
+0

" Cela ressemble à un peu un hack, cependant "- quelque chose qui peut être dit à propos de beaucoup de bonnes solutions dans R. +1 –

+0

Merci pour votre réponse détaillée @Paul. Mais en fait, j'ai toujours un problème parce que je stocke mes variables dans un cadre de données. 'df <- tribut (~ var1, ~ var2, ~ score, données3 $ var1, données3 $ var2, données3 $ score) df%>% mutate_if (est.caracter, facteur, levels = c ('data3 $ var1' , 'data3 $ var2'))%>% xtabs (score ~ ​​var1 + var2,., drop.unused.levels = F)%>% '+' (., t (.)) ' – Brenna

+0

La façon dont vous utilisez 'tribble' donnera lieu à des colonnes de liste. Vous pouvez simplement utiliser 'data3%>% mutate_if (est.caractère, facteur, niveaux = c ('A', 'B', 'C', 'D'))%>% xtabs (score ~ ​​var1 + var2,., drop.unused.levels = F)%>% ' + '(., t (.)) ' – Paul

3

Voici une méthode de base R utilisant l'indexation matricielle sur des vecteurs de caractères.

## set up matrix 
# get names for row and columns 
nameVals <- sort(unique(unlist(dat[1:2]))) 
# construct 0 matrix of correct dimensions with row and column names 
myMat <- matrix(0, length(nameVals), length(nameVals), dimnames = list(nameVals, nameVals)) 

# fill in the matrix with matrix indexing on row and column names 
myMat[as.matrix(dat[c("var1", "var2")])] <- dat[["value"]] 

Ce retour

myMat 
    A B C D 
A 0 4 0 0 
B 0 0 0 1 
C 0 0 0 5 
D 2 0 0 0 

Pour plus de détails sur la façon dont cette indexation fonctionne, voir les tableaux et Matrices section du fichier d'aide ?"[". Le quatrième paragraphe traite de cette forme d'indexation.

Notez que je suppose que les deux premières variables sont des vecteurs de caractères plutôt que des facteurs. Cela rend un peu plus facile, puisque je n'ai pas besoin d'utiliser as.character pour les contraindre.

Pour convertir le résultat en un nom de données, encapsulez-le simplement dans as.data.frame.

données

dat <- 
structure(list(var1 = c("A", "C", "D", "B"), var2 = c("B", "D", 
"A", "D"), value = c(4L, 5L, 2L, 1L)), .Names = c("var1", "var2", 
"value"), class = "data.frame", row.names = c(NA, -4L))