2012-11-29 5 views
1

Donc je trie une matrice une ligne à la fois en descendant qui est 130X130, et je veux créer une nouvelle matrice où le nom de la rangée est le même, mais la colonne de chaque rangée triée les noms sont où les données étaient et les données entre parenthèses à côté du nom de colonne correspondant. C'est un peu comme créer un tableau psuedo3D de la dimension 130x130x2 et ensuite le condenser en une matrice 130x130 sans noms de colonne. Voici un petit exemple.Condenser des données 3D dans une matrice en R

Exemple

 A B C D 
    A 14 82 18 50 
    B 39 95 27 19 
    C 60 40 32 15 
    D 70 31 69 31 

Ce que je veux

A B(82) D(50) C(18) A(14) 
    B B(95) A(39) C(27) D(19) 
    C A(60) B(40) C(32) D(15) 
    D A(70) C(69) B(31) D(31) 

J'espère que cela a du sens!

Merci!

Répondre

6

Ici, vous allez:

Première , recréer vos données:

x <- read.table(text=" 
     A B C D 
    A 14 82 18 50 
    B 39 95 27 19 
    C 60 40 32 15 
    D 70 31 69 31", header=TRUE) 

Deux apply() s, un paste() et un matrix(), et le reste est les détails:

o <- apply(x, 1, order, decreasing=TRUE) 
v <- apply(x, 1, sort, decreasing=TRUE) 

matrix(paste(names(x)[o], t(v)), ncol=4, byrow=TRUE) 

    [,1] [,2] [,3] [,4] 
[1,] "B 82" "D 50" "C 18" "A 14" 
[2,] "B 95" "A 39" "C 27" "D 19" 
[3,] "A 60" "B 40" "C 32" "D 15" 
[4,] "A 70" "C 69" "B 31" "D 31" 

EDIT: D'après un commentaire par Jeff Allen, cela peut être encore simplifiée:

t(apply(x, 1, function(x){s <- order(x, decreasing=TRUE); paste(names(x)[s], x[s])})) 

    [,1] [,2] [,3] [,4] 
A "B 82" "D 50" "C 18" "A 14" 
B "B 95" "A 39" "C 27" "D 19" 
C "A 60" "B 40" "C 32" "D 15" 
D "A 70" "C 69" "B 31" "D 31" 

(comme il n'a qu'un seul apply il devrait être encore plus rapide.)

+0

+1. Deux fois plus vite que le mien. –

+0

@JeffAllen Basé sur vos commentaires, je l'ai simplifié plus loin pour avoir un seul 'apply' – Andrie

+0

J'aime le dernier. Vous pouvez aussi remplacer 'paste (...)' par sprintf ("% s (% d)", noms (x) [s], x [s]) 'pour correspondre au format de sortie de l'OP. – flodel

3

J'espère que quelqu'un proposera une solution vectorisée, mais voici une option:

sortTab <- function(tab){ 
    for (i in 1:nrow(tab)){ 
     #Get the order of the elements in the current row 
     ord <- order(tab[i,], decreasing=TRUE) 

     #get the associated column names and values with this ordering  
     res <- paste(colnames(tab)[ord], "(", tab[i,ord], ")", sep="") 

     #assign back to the data.frame 
     tab[i,] <- res 

    } 
    tab 
} 

Et un test en utilisant vos données:

txt <- textConnection("  A B C D 
    A 14 82 18 50 
    B 39 95 27 19 
    C 60 40 32 15 
    D 70 31 69 31") 
tab <- read.table(txt) 

> sortTab(tab) 
     A  B  C  D 
A B(82) D(50) C(18) A(14) 
B B(95) A(39) C(27) D(19) 
C A(60) B(40) C(32) D(15) 
D A(70) C(69) B(31) D(31) 
+0

Après un examen plus approfondi, voici une discussion sur la limitation que j'ai rencontrée avec 'apply()' qui a forcé une boucle 'for'. http://stackoverflow.com/questions/2545879/row-column-counter-in-apply-functions?rq=1. Je ne suis pas entièrement sûr que cela aiderait à la performance ici. Peut-être que quelqu'un peut suggérer une amélioration. –

+0

Par intérêt, à quelle limitation de «appliquer» faites-vous référence? – Andrie

+0

J'aurais aimé quelque chose comme: 'apply (tabulation, 1, fonction (x) {x <- coller (ordre (x) ...)})'. Mais sans passer par référence, ça ne va pas marcher. –

Questions connexes