2013-03-18 3 views
1

je un tableau similaire à celui-ci, et souhaite calculer le rapport entre la colonne A et B par exemple:calcul de ratios et les mettre dans une matrice en R

   A B  C  D E  F 
    [1,] 187 174 183 115 101 104 
    [2,] 451 166 177 842 101 133 
    [3,] 727 171 187 12803 98 134 
    [4,] 1532 181 196 730 98 108 
    [5,] 4139 188 214 20358 105 159 
    [6,] 689 185 211 1633 110 162 
    [7,] 1625 184 195 2283 109 114 
    [8,] 771 181 190 904 105 110 
    [9,] 950 177 190 1033 106 112 
    [10,] 703 180 191 463 106 110 
    [11,] 2052 178 188 2585 100 105 
    [12,] 1161 178 187 2874 99 110 
    [13,] 214 175 184 173 98 110 
    [14,] 473 184 191 971 104 111 
    [15,] 756 185 193 14743 107 114 

Je veux créer une nouvelle matrice qui a toutes les lignes précédentes que de nouvelles lignes et de colonnes (15 lignes et 15 colonnes) comme si (valeurs entre parenthèses sont des espaces réservés pour les ratios calculés):

  [,1] [,2]  [,3] [,4]  
[1,] (A1:B1) (A1:B2) (A1:B3) (A1:B4) ... 
[2,] 
[3,] 
[4,] 
... 

C'est peut-être pas le meilleur exemple, mais je J'espère que ce n'est pas confus. Pour calculer les rapports A1: B1, A2: B2, A3: B3 je pouvais faire quelque chose comme

data.matrix(data["A"]/data["B"]) 

Et de le faire pour tout, je ferais quelque chose comme

data.matrix(data[1,]/data[1,1]) 
data.matrix(data[1,]/data[1,2]) 
... 

et ainsi de suite . Cela semble être beaucoup de travail et peut-être quelqu'un connaît une méthode plus rapide et plus efficace

EDIT

Je pensais que la fonction Combn fonctionnerait, mais je compris qu'il ne fonctionne pas. Lorsque j'ai une matrice de la colonne 2, par exemple

 A  B 
[1,] 187 115 
[2,] 451 842 
[3,] 727 12803 
[4,] 1532 730 
[5,] 4139 20358 
[6,] 689 1633 
[7,] 1625 2283 
[8,] 771 904 
[9,] 950 1033 
[10,] 703 463 
[11,] 2052 2585 
[12,] 1161 2874 
[13,] 214 173 
[14,] 473 971 
[15,] 756 14743 

J'utiliser la fonction combn pour calculer tous les rapports possibles (A1: B1, A1: B2, ... A2: B1, A2 B2 ...) Je viens d'obtenir le résultat de A1 vs toutes les valeurs de B.

> combn(ncol(data), 2, function(x) data[,x[1]]/data[,x[2]]) 
[,1] 
[1,] 1.62608696 
[2,] 0.53562945 
[3,] 0.05678357 
[4,] 2.09863014 
[5,] 0.20331074 
[6,] 0.42192284 
[7,] 0.71178274 
[8,] 0.85287611 
[9,] 0.91965150 
[10,] 1.51835853 
[11,] 0.79381044 
[12,] 0.40396660 
[13,] 1.23699422 
[14,] 0.48712667 
[15,] 0.05127857 

Ou peut-être que je ne comprends pas la fonction combn et je suis en train de faire quelque chose de mal ici ...

+0

Que faut-il attendre du résultat de ces deux colonnes? les rapports sont «A1: B1», «A2: B2» dans une seule colonne est le résultat pour le moment. – mnel

+0

Voulez-vous A1: B1, A1: B2 ... comme première rangée, puis A2: B1, A2: B2, .. comme deuxième rangée et ainsi de suite? –

+0

oui, exactement comme ça –

Répondre

1

Edit: Je semble avoir mal compris la question. La réponse est encore plus simple en utilisant outer:

# gives the same 15*15 matrix as geektrader's 
outer(mm[,1], mm[,2], '/') 

Vieille réponse (non correcte):

Vous devez utiliser combn:

# combn(ncol(mm), 2) gives you all possible combinations 
#  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] 
# [1,] 1 1 1 1 1 2 2 2 2  3  3  3  4  4  5 
# [2,] 2 3 4 5 6 3 4 5 6  4  5  6  5  6  6 

# it also accepts a function argument. we can use it to divide 
# respective columns 
mm.div <- combn(ncol(mm), 2, function(x) mm[,x[1]]/mm[,x[2]]) 

# set column names the matrix 
colnames(mm.div) <- combn(colnames(mm), 2, paste, collapse="") 
+0

Super, merci, c'était exactement ce que je cherchais! –

+0

Je pensais que ça marcherait, mais j'ai compris que ça ne faisait pas ce que je voulais. J'ai ajouté mon problème à mon premier post après "EDIT", j'apprécierais si vous pouviez m'aider ici –

+0

@bluewoodtree --- essayez de transposer les résultats? – mnel

0

je pourrais être complètement à côté de la point ici, mais pourquoi ne pas simplement utiliser un couple pour les boucles? J'ai écrit une fonction rapide, alors vous pourriez passer les paires à.

Par exemple:

A <- rnorm(15) 
B <- rnorm(15) 
data <- data.frame(A,B) 

ratio <- function(input1, input2){ 
    out <- matrix(0, nrow=length(input1), ncol=length(input1)) 
    k <- 1 
    for (i in 1:length(input1)){ 
     for (j in 1:length(input1)){ 
      out[k, j] <- input1[k]/input2[j] 
     } 
     k <- k + 1 
    } 
    return(out) 
} 

ratio(data$A, data$B) 

EDIT

Une autre pensée. Pour utiliser la fonction de faire toutes les paires possibles de rapports, vous pouvez simplement ajouter une autre boucle, comme ceci:

combs <- combn(1:4, 2) 
out <- list() 
for (i in 1:(length(combs)/2)){ 
    out[[i]] <- ratio(data[,combs[1,i]], data[,combs[2,i]]) 
} 

Hope that helps!

+0

Les boucles en tant que telles sont mal vues dans R. –

+0

Parce que cela sera inefficace car 'R' est vectorisé. – mnel

+0

Cela a du sens, désolé! geektrader, votre solution est définitivement plus élégante, merci de l'avoir posté. –

2

Vous pouvez obtenir ce que vous voulez en utilisant expand.grid, apply et matrix fonctions ci-dessous

Je suppose ce que vous voulez est la matrice comme

A1/B1 A1/B2 A1/B3 ... 
A2/B1 A2/B2 A2/B3 ... 
... ... ... ... 
... ... ... ... 

Voici le code pour le faire. Explication dans les commentaires

txt <- "A B  C  D E  F\n187 174 183 115 101 104\n451 166 177 842 101 133\n727 171 187 12803 98 134\n1532 181 196 730 98 108\n4139 188 214 20358 105 159\n689 185 211 1633 110 162\n1625 184 195 2283 109 114\n771 181 190 904 105 110\n950 177 190 1033 106 112\n703 180 191 463 106 110\n2052 178 188 2585 100 105\n1161 178 187 2874 99 110\n214 175 184 173 98 110\n473 184 191 971 104 111\n756 185 193 14743 107 114" 

data <- as.matrix(read.table(textConnection(txt), header = TRUE)) 

# expand.grid : creates every combination of one element each from column A and 
# B with elements of B repeated first 

# apply : calls function(x) { x[1]/x[2]) } for every combination outputted by 
# expand.grid 

# matrix : converts the result of apply into matrix. dimnames arguments sets 
# rownames and colnames for easy verification for us 

result <- matrix(apply(expand.grid(data[, "A"], data[, "B"]), 1, function(x) x[1]/x[2]), 
    nrow = nrow(data), dimnames = list(data[, "A"], data[, "B"])) 

# note that we have set rownames for result to be values of A and colnames for 
# result to be value of B 
result 
##   174  166  171  181  188  185  184 
## 187 1.074713 1.126506 1.093567 1.033149 0.9946809 1.010811 1.016304 
## 451 2.591954 2.716867 2.637427 2.491713 2.3989362 2.437838 2.451087 
## 727 4.178161 4.379518 4.251462 4.016575 3.8670213 3.929730 3.951087 
## 1532 8.804598 9.228916 8.959064 8.464088 8.1489362 8.281081 8.326087 
## 4139 23.787356 24.933735 24.204678 22.867403 22.0159574 22.372973 22.494565 
## 689 3.959770 4.150602 4.029240 3.806630 3.6648936 3.724324 3.744565 
## 1625 9.339080 9.789157 9.502924 8.977901 8.6436170 8.783784 8.831522 
## 771 4.431034 4.644578 4.508772 4.259669 4.1010638 4.167568 4.190217 
## 950 5.459770 5.722892 5.555556 5.248619 5.0531915 5.135135 5.163043 
## 703 4.040230 4.234940 4.111111 3.883978 3.7393617 3.800000 3.820652 
## 2052 11.793103 12.361446 12.000000 11.337017 10.9148936 11.091892 11.152174 
## 1161 6.672414 6.993976 6.789474 6.414365 6.1755319 6.275676 6.309783 
## 214 1.229885 1.289157 1.251462 1.182320 1.1382979 1.156757 1.163043 
## 473 2.718391 2.849398 2.766082 2.613260 2.5159574 2.556757 2.570652 
## 756 4.344828 4.554217 4.421053 4.176796 4.0212766 4.086486 4.108696 
##   181  177  180  178  178  175  184 
## 187 1.033149 1.056497 1.038889 1.050562 1.050562 1.068571 1.016304 
## 451 2.491713 2.548023 2.505556 2.533708 2.533708 2.577143 2.451087 
## 727 4.016575 4.107345 4.038889 4.084270 4.084270 4.154286 3.951087 
## 1532 8.464088 8.655367 8.511111 8.606742 8.606742 8.754286 8.326087 
## 4139 22.867403 23.384181 22.994444 23.252809 23.252809 23.651429 22.494565 
## 689 3.806630 3.892655 3.827778 3.870787 3.870787 3.937143 3.744565 
## 1625 8.977901 9.180791 9.027778 9.129213 9.129213 9.285714 8.831522 
## 771 4.259669 4.355932 4.283333 4.331461 4.331461 4.405714 4.190217 
## 950 5.248619 5.367232 5.277778 5.337079 5.337079 5.428571 5.163043 
## 703 3.883978 3.971751 3.905556 3.949438 3.949438 4.017143 3.820652 
## 2052 11.337017 11.593220 11.400000 11.528090 11.528090 11.725714 11.152174 
## 1161 6.414365 6.559322 6.450000 6.522472 6.522472 6.634286 6.309783 
## 214 1.182320 1.209040 1.188889 1.202247 1.202247 1.222857 1.163043 
## 473 2.613260 2.672316 2.627778 2.657303 2.657303 2.702857 2.570652 
## 756 4.176796 4.271186 4.200000 4.247191 4.247191 4.320000 4.108696 
##   185 
## 187 1.010811 
## 451 2.437838 
## 727 3.929730 
## 1532 8.281081 
## 4139 22.372973 
## 689 3.724324 
## 1625 8.783784 
## 771 4.167568 
## 950 5.135135 
## 703 3.800000 
## 2052 11.091892 
## 1161 6.275676 
## 214 1.156757 
## 473 2.556757 
## 756 4.086486 
+0

Ça marche! Merci beaucoup. C'est vraiment un super article, et j'apprécie vraiment les explications! Si vous avez juste une question de plus: je ne sais toujours pas quand utiliser 'as.matrix()' et 'data.matrix', par exemple je peux remplacer' data <- as.matrix (... 'par' data < - data.matrix (... 'et le résultat sera le même –

+1

@bluewoodtree voir'? data.matrix' dans R. La section de valeur de ces pages d'aide indique qu'il renvoie 'If frame inherits from class" data.frame ", une matrice entière ou numérique ayant les mêmes dimensions que frame, avec des noms de variables tirés de row.names (ou de NULL, en fonction de rownames.force) et de noms Sinon, le résultat de as.matrix.' –

+0

@geektrader , oui, il semble que je me trompe. (+1). – Arun