toutes les personnes! Supposons que j'ai un vecteur de longueur n (n + 1) / 2:
a = (a_11, a_12, a_22, ...., a_nn)
Maintenant, j'aimerais le transformer en une matrice symétrique, c'est à dire
Je pourrais attribuer la valeur une par une, mais je me demande s'il y en a plus rapidement pour créer cette matrice? Merci beaucoup!!
5 Réponses :
sq.m[ upper.tri(sq.m) ] <- sq.m[lower.tri(sq.m)] > sq.m [,1] [,2] [,3] [,4] [,5] [1,] 1 2 3 5 10 [2,] 2 7 4 8 14 [3,] 3 8 13 9 15 [4,] 4 9 14 19 20 [5,] 5 10 15 20 25
OP n'a pas n ^ 2 éléments dans le vecteur d'entrée. Je pense que l'intention est de dupliquer certains éléments sur la diagonale pour en créer un
Sa présentation du problème m'a suggéré qu'il avait n ^ 2 éléments. Quelle est votre preuve du contraire.?
Suppose I have a vector of length n(n+1)/2:
Vous n'avez donc que les éléments triangulaires inférieurs? Ah, maintenant je vois. Il n'a que les éléments triangulaires diagonaux et supérieurs.
Peu importe, c'est une matrice symétrique. Il peut être triangulaire supérieur ou inférieur.
@RonakShah Vous lisez mieux le problème que moi. Vous obtenez mon vote.
Tu peux essayer :
#define n n <- 2 #Create n(n+1)/2 objects in global environment #OP already has that a_11 <- 5 a_12 <- 9 a_22 <- 8 #Create n X n matrix with NA mat <- matrix(nrow = n, ncol = n) #Get all the individual objects in one vector vec <- unlist(mget(ls(pattern = 'a_')), use.names = FALSE) #Replace upper (or lower) triangular elements with it mat[upper.tri(mat, diag = TRUE)] <- vec #Copy the elements to other half. mat[lower.tri(mat)] <- mat[upper.tri(mat)] # [,1] [,2] #[1,] 5 9 #[2,] 9 8
Vous pouvez écrire une fonction qui fait ceci:
SI vous aviez votre vecteur comme a11,a12,a13..a1n,a22,a23..a2n, a33,..a3n,..ann
Vous pouvez faire:
vec2mat <- function(x){ p <- sqrt(1 + 8 * length(x))/ 2 - 0.5 m <- matrix(0, p, p) m[upper.tri(m, diag = TRUE)] <- x m[lower.tri(m)] <- t(m)[lower.tri(m)] m } vec2mat(1:10) [,1] [,2] [,3] [,4] [1,] 1 2 4 7 [2,] 2 3 5 8 [3,] 4 5 6 9 [4,] 7 8 9 10
Maintenant:
vec2mat(1:6) [,1] [,2] [,3] [1,] 1 2 3 [2,] 2 4 5 [3,] 3 5 6 vec2mat(1:10) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 2 5 6 7 [3,] 3 6 8 9 [4,] 4 7 9 10
si vous aviez a11, a12,a22,a31, a32, a33...
vec2mat <- function(x){ p <- sqrt(1 + 8 * length(x))/ 2 - 0.5 m <- matrix(0, p, p) m[lower.tri(m, diag = TRUE)] <- x m[upper.tri(m)] <- (t(m))[upper.tri(m)] m }
Merci beaucoup :) Cela fonctionne vraiment!
pour 1000 éléments ça plante ... pourquoi ça?
@ManosPapadakis car vous ne pouvez pas avoir 1000 éléments. Notez que le nombre doit être un nombre triangulaire. c'est-à-dire le triangle inférieur ou triangle supérieur d'une matrice carrée comprenant la diagonale. donc le nombre, c'est-à-dire le vecteur, doit avoir une longueur de 990 s'il s'agit d'un carré de 44 lignes et 44 colonnes ou 1035 s'il s'agit d'un carré de 45 lignes et 45 colonnes.
Merci beaucoup!
Vous pouvez créer une matrice clairsemée comme celle-ci:
a <- 1:6 n <- as.integer(-0.5 + sqrt(0.25 + 2 * length(a))) library(Matrix) sparseMatrix(x = a, dims = c(n, n), symmetric = TRUE, i = sequence(1:n), j = rep(1:n, 1:n)) #3 x 3 sparse Matrix of class "dsCMatrix" # #[1,] 1 2 4 #[2,] 2 3 5 #[3,] 4 5 6
Utilisez as.matrix
sur le résultat si vous avez besoin d'une matrice dense. Si l'ordre de votre vecteur est différent de celui que vous montrez (par exemple, ligne-majeure comme le supposent certaines des autres réponses), vous devez ajuster légèrement le calcul de i
et j
.
si vous avez de gros vecteurs et que la vitesse compte, vous pouvez utiliser cette fonction (tirée de @Onyambu) qui utilise le package Rfast.
vec2mat_rfast <- function(x){ p <- sqrt(1 + 8 * length(x))/ 2 - 0.5 m <- matrix(0, p, p) m[Rfast::upper_tri(m, diag = TRUE)] <- x m[Rfast::lower_tri(m)] <- Rfast::transpose(m)[Rfast::lower_tri(m)] m } vec2mat <- function(x){ p <- sqrt(1 + 8 * length(x))/ 2 - 0.5 m <- matrix(0, p, p) m[upper.tri(m, diag = TRUE)] <- x m[lower.tri(m)] <- t(m)[lower.tri(m)] m } y=numeric(500500) > microbenchmark::microbenchmark(a<-vec2mat(y),b<-vec2mat_rfast(y),times = 10) Unit: milliseconds expr min lq mean median uq max neval a <- vec2mat(y) 88.9461 101.5294 114.96752 108.86680 112.9854 180.9679 10 b <- vec2mat_rfast(y) 33.1351 34.5294 49.61295 45.26955 62.8214 80.5069 10 > all.equal(a,b) [1] TRUE
Fournir un vecteur réel et la sortie attendue correspondante au lieu des indices faciliterait beaucoup la réponse.
est-ce le cas que a_12 dans le vecteur d'entrée doit être inséré à la fois dans a_12 et a_21 dans la matrice?