Forneci primeiro o que agora acredito ser uma resposta abaixo do ideal; portanto, editei minha resposta para começar com uma sugestão melhor.
Usando o método Vine
Neste tópico: Como gerar eficientemente matrizes de correlação aleatória positiva-semidefinida? - Descrevi e forneci o código para dois algoritmos eficientes de geração de matrizes de correlação aleatória. Ambos vêm de um artigo de Lewandowski, Kurowicka e Joe (2009).
Por favor, veja minha resposta lá para muitas figuras e código do matlab. Aqui, gostaria apenas de dizer que o método vine permite gerar matrizes de correlação aleatórias com qualquer distribuição de correlações parciais (observe a palavra "parcial") e pode ser usado para gerar matrizes de correlação com grandes valores fora da diagonal. Aqui está a figura relevante desse segmento:
±1
Eu acho que essas distribuições são razoavelmente "normais", e pode-se ver como o desvio padrão aumenta gradualmente. Devo acrescentar que o algoritmo é muito rápido. Veja o tópico vinculado para obter detalhes.
Minha resposta original
Uma modificação direta do seu método pode fazer o truque (dependendo de quão perto você deseja que a distribuição esteja do normal). Esta resposta foi inspirada nos comentários do @ cardinal acima e na resposta do @ psarka à minha própria pergunta Como gerar uma grande matriz de correlação aleatória com várias correlações fortes presentes?
XX1000×100[−a/2,a/2]a=0,1,2,5a=0X⊤X1/1000−−−−√a>0aa=0,1,2,5
Todas essas matrizes são, obviamente, positivas. Aqui está o código do matlab:
offsets = [0 1 2 5];
n = 1000;
p = 100;
rng(42) %// random seed
figure
for offset = 1:length(offsets)
X = randn(n,p);
for i=1:p
X(:,i) = X(:,i) + (rand-0.5) * offsets(offset);
end
C = 1/(n-1)*transpose(X)*X; %// covariance matrix (non-centred!)
%// convert to correlation
d = diag(C);
C = diag(1./sqrt(d))*C*diag(1./sqrt(d));
%// displaying C
subplot(length(offsets),3,(offset-1)*3+1)
imagesc(C, [-1 1])
%// histogram of the off-diagonal elements
subplot(length(offsets),3,(offset-1)*3+2)
offd = C(logical(ones(size(C))-eye(size(C))));
hist(offd)
xlim([-1 1])
%// QQ-plot to check the normality
subplot(length(offsets),3,(offset-1)*3+3)
qqplot(offd)
%// eigenvalues
eigv = eig(C);
display([num2str(min(eigv),2) ' ... ' num2str(max(eigv),2)])
end
A saída deste código (valores próprios mínimos e máximos) é:
0.51 ... 1.7
0.44 ... 8.6
0.32 ... 22
0.1 ... 48