2013-04-15 11 views
5

W R istnieje funkcja (cm.rnorm.cor, z pakietu CreditMetrics), która pobiera ilość próbek, ilość zmiennych i macierz korelacji w celu utworzenia skorelowanych danych.Generowanie skorelowanych danych w Pythonie (3.3)

Czy istnieje odpowiednik w Pythonie?

+0

Niestety, moje złe, na Pythonie 3.3. – PascalVKooten

+0

Whaaat ... Wsparcie zostało dodane naprawdę niedawno! Dzięki za przypomnienie. – PascalVKooten

+0

@Dualinity, w nieco mniej humorystycznym tonie, obok wspaniałej kolekcji pakietów z Blendera, naprawdę sugeruję wypróbowanie Pythona (X, Y). Jest to zbiór pakietów Pythona do rozwoju naukowego + IPython + Great IDE o nazwie Spyder. http://code.google.com/p/pythonxy/ – Oz123

Odpowiedz

9

numpy.random.multivariate_normal to funkcja, której potrzebujesz.

przykład:

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() 

Wynik:

enter image description here

Patrz także CorrelatedRandomSamples w scipy Cookbook.

5

Jeśli Cholesky-rozkładają macierz kowariancji C do L L^T i generuje losowe niezależne wektor x, następnie Lx będzie losowy wektor z kowariancji 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

Zobacz: Cholesky decomposition


Jeśli chcesz wygenerować dwie serie, X i Y, ze szczególnym (Pearson) correlation coefficient (np 0,2):

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

można wybrać macierz kowariancji być

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

To sprawia, że ​​cov(X,Y) = 0.2 i wariancje, var(X) i var(Y) zarówno równy 1. Tak rho będzie równy 0,2.

Na przykład poniżej generujemy pary skorelowanych serii, X i Y, 1000 razy. Następnie wykreślić histogram współczynników korelacji:

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

Jak widać, współczynniki korelacji są zazwyczaj blisko 0,2, ale dla każdej próbki, korelacja najprawdopodobniej nie będzie 0,2 dokładnie .

+0

Czy wiesz, jak uzyskać dokładne dane o korelacji, powiedzmy, 0,2 (z niewielką tolerancją)? – PascalVKooten

+0

czy to już jest dokładne? – PascalVKooten

+0

Co to jest "numpy.random.multivariate_normal' robi pod maską? Ponieważ porównałem ten pierwszy z podejściem cholesky i stwierdziłem, że ten ostatni jest znacznie szybszy, szczególnie w przypadku większych danych wymiarowych (np. Kilka tysięcy). Czy podejście cholesky działa tylko dla pewnych konkretnych typów macierzy kowariancji? Moja matryca ma tylko przekątną lub jest bardzo rzadka. – Jason

Powiązane problemy