2013-08-14 16 views
6

Załóżmy, że mam pandas.DataFrame o nazwie df. Kolumny df reprezentują różne osoby, a oś indeksu reprezentuje czas, więc wpis (i, j) jest indywidualną obserwacją j dla okresu czasu i możemy przyjąć, że wszystkie dane są typu float prawdopodobnie z wartościami NaN.Szybki sposób na zobaczenie wspólnej liczby obserwacji dla macierzy korelacji Python Pandy

W moim przypadku mam około 14 000 kolumn i kilkaset wierszy.

pandas.corr da mi z powrotem matrycę korelacji 14 000 na 14 000 i jej wydajność w czasie jest w porządku dla mojej aplikacji.

Ale chciałbym również wiedzieć, dla każdej pary osób (j_1, j_2), ile nie-zerowych obserwacji poszło do obliczeń korelacji, więc mogę wyizolować komórki korelacyjne, które cierpią z powodu słabego zasięgu danych.

Najlepszą udało mi się wymyślić jest następujący:

not_null_locations = pandas.notnull(df).values.astype(int) 
common_obs = pandas.DataFrame(not_null_locations.T.dot(not_null_locations), 
           columns=df.columns, index=df.columns) 

Ślad pamięci i szybkość to zaczynają być nieco problematyczne.

Czy istnieje szybszy sposób na uzyskanie wspólnych obserwacji za pomocą pandas?

+2

można częściowo rozwiązać ten problem przez przepuszczenie 'min_periods'' do corr (np Jego odcięcia gdzie wymagają, aby minimalna liczba obserwacji; nie bezpośrednio odpowiedzieć, ale może dać ci„wystarczająco dobre”odpowiedzieć – Jeff

+0

To świetna propozycja, ale pracuję w systemie produkcyjnym, który wymaga Pand w wersji 0.8.0 i wygląda na to, że 'min_periods' został dodany w nowszej wersji Nic nie mogę zrobić z nieaktualną wersją boi się . – ely

+0

można * dodać * to w kodzie (i rekompilować), jeśli na Linuksie (gdzie całkiem łatwo) ..... to tylko zmiana linii (oczywiście "produkcja" może wyklucza to ....) – Jeff

Odpowiedz

3

Możesz to zrobić, ale musisz wykonać cytonizację (w przeciwnym razie znacznie wolniej); jednak pamięci ślad powinien być lepiej (to daje liczbę obserwacji Nan swój daje liczbę ważnych spostrzeżeń, ale łatwo wymienialne)

l = len(df.columns) 
results = np.zeros((l,l)) 
mask = pd.isnull(df) 
for i, ac in enumerate(df): 
    for j, bc in enumerate(df): 
      results[j,i] = (mask[i] & mask[j]).sum() 
results = DataFrame(results,index=df.columns,columns=df.columns) 
3

można rzeczywiście dokonać @ odpowiedź Jeffa trochę szybciej tylko iteracji do (ale nie włączając) i + 1 w pętli zagnieżdżonej, a ponieważ korelacja jest symetryczna, można przypisać wartości w tym samym czasie. Możesz także przenieść dostęp mask[i] poza zagnieżdżoną pętlą, co jest niewielką optymalizacją, ale może przynieść trochę poprawy wydajności dla bardzo dużych ramek.

l = len(df.columns) 
results = np.zeros((l,l)) 
mask = pd.isnull(df) 
for i in range(l): 
    maski = mask[i] 
    for j in range(i + 1): 
      results[i,j] = results[j,i] = (maski & mask[j]).sum() 
results = DataFrame(results,index=df.columns,columns=df.columns) 
Powiązane problemy