2013-04-15 18 views
5

In R è presente una funzione (cm.rnorm.cor, dal pacchetto CreditMetrics) che accetta la quantità di campioni, la quantità di variabili e una matrice di correlazione per creare dati correlati.Generare dati correlati in Python (3.3)

Esiste un equivalente in Python?

+0

Mi dispiace, mio ​​male, su Python 3.3. – PascalVKooten

+0

Whaaat ... Il supporto è stato aggiunto davvero di recente! Grazie per avermi ricordato. – PascalVKooten

+0

@Dualinity, con un tono meno umoristico, oltre alla grande raccolta di pacchetti di Blender, ti suggerisco di provare Python (X, Y). È una raccolta di pacchetti Python per lo sviluppo scientifico + IPython + Grande IDE chiamato spyder. http://code.google.com/p/pythonxy/ – Oz123

risposta

9

numpy.random.multivariate_normal è la funzione che si desidera.

Esempio:

import numpy as np 
import matplotlib.pyplot as plt 


num_samples = 400 

# The desired mean values of the sample. 
mu = np.array([5.0, 0.0, 10.0]) 

# The desired covariance matrix. 
r = np.array([ 
     [ 3.40, -2.75, -2.00], 
     [ -2.75, 5.50, 1.50], 
     [ -2.00, 1.50, 1.25] 
    ]) 

# Generate the random samples. 
y = np.random.multivariate_normal(mu, r, size=num_samples) 


# Plot various projections of the samples. 
plt.subplot(2,2,1) 
plt.plot(y[:,0], y[:,1], 'b.') 
plt.plot(mu[0], mu[1], 'ro') 
plt.ylabel('y[1]') 
plt.axis('equal') 
plt.grid(True) 

plt.subplot(2,2,3) 
plt.plot(y[:,0], y[:,2], 'b.') 
plt.plot(mu[0], mu[2], 'ro') 
plt.xlabel('y[0]') 
plt.ylabel('y[2]') 
plt.axis('equal') 
plt.grid(True) 

plt.subplot(2,2,4) 
plt.plot(y[:,1], y[:,2], 'b.') 
plt.plot(mu[1], mu[2], 'ro') 
plt.xlabel('y[1]') 
plt.axis('equal') 
plt.grid(True) 

plt.show() 

Risultato:

enter image description here

Vedi anche CorrelatedRandomSamples nel SciPy Cookbook.

5

Se Cholesky-decomporre una matrice di covarianza C in L L^T, e generare un indipendente vettore casuale x, quindi Lx sarà un vettore casuale con covarianza C.

import numpy as np 
import matplotlib.pyplot as plt 
linalg = np.linalg 
np.random.seed(1) 

num_samples = 1000 
num_variables = 2 
cov = [[0.3, 0.2], [0.2, 0.2]] 

L = linalg.cholesky(cov) 
# print(L.shape) 
# (2, 2) 
uncorrelated = np.random.standard_normal((num_variables, num_samples)) 
mean = [1, 1] 
correlated = np.dot(L, uncorrelated) + np.array(mean).reshape(2, 1) 
# print(correlated.shape) 
# (2, 1000) 
plt.scatter(correlated[0, :], correlated[1, :], c='green') 
plt.show() 

enter image description here

riferimento: Vedere Cholesky decomposition


Se si desidera generare due serie, X e Y, con una particolare (Pearson) correlation coefficient (ad esempio 0,2):

rho = cov(X,Y)/sqrt(var(X)*var(Y)) 

si potrebbe scegliere la matrice di covarianza di essere

cov = [[1, 0.2], 
     [0.2, 1]] 

Questo rende la cov(X,Y) = 0.2, e le varianze, var(X) e var(Y) sia uguale a 1. Quindi rho sarebbe uguale 0,2.

Ad esempio, di seguito vengono generate coppie di serie correlate, X e Y, 1000 volte. Poi abbiamo tracciare un istogramma dei coefficienti di correlazione:

import numpy as np 
import matplotlib.pyplot as plt 
import scipy.stats as stats 
linalg = np.linalg 
np.random.seed(1) 

num_samples = 1000 
num_variables = 2 
cov = [[1.0, 0.2], [0.2, 1.0]] 

L = linalg.cholesky(cov) 

rhos = [] 
for i in range(1000): 
    uncorrelated = np.random.standard_normal((num_variables, num_samples)) 
    correlated = np.dot(L, uncorrelated) 
    X, Y = correlated 
    rho, pval = stats.pearsonr(X, Y) 
    rhos.append(rho) 

plt.hist(rhos) 
plt.show() 

enter image description here

Come si può vedere, i coefficienti di correlazione sono generalmente vicino 0.2, ma per qualsiasi dato campione, la correlazione molto probabilmente non essere 0,2 esattamente .

+0

Sapresti come ottenere che i dati abbiano esattamente una correlazione, diciamo, di 0.2 (con una tolleranza simile)? – PascalVKooten

+0

o è già esatto? – PascalVKooten

+0

Cosa sta facendo 'numpy.random.multivariate_normal' sotto il cofano? Perché ho confrontato il primo con l'approccio Cholesky e ho trovato quest'ultimo molto più veloce, in particolare per dati dimensionali di grandi dimensioni (come poche migliaia). L'approccio di Cholesky funziona solo per alcuni tipi specifici di matrice di covarianza? La mia cov-matrix è solo diagonale, o molto sparsa. – Jason

Problemi correlati