2016-01-20 10 views
6

pracuję z następującymi danymi Panel w MultiIndex pand DataFrame zwanych df_data:próbkowania od MultiIndex DataFrame

   y   x 
n time      
0 0  0.423607 -0.307983 
    1  0.565563 -0.333430 
    2  0.735979 -0.453137 
    3  0.962857 1.671106 
1 0  0.772304 1.221366 
    1  0.455327 -1.024852 
    2  0.864768 0.609867 
    3  0.334429 -2.567936 
2 0  0.435553 -0.259228 
    1  0.221501 0.484677 
    2  0.773628 0.650288 
    3  0.293902 0.566452 

n indeksy indywidualnej (istnieją 500 z nich), t indeksuje czasu. To zrównoważony panel. Chciałbym utworzyć losową próbkę z nn=100 osób z wymianą. Ponadto, jeśli dana osoba trafi do próbki losowej, wówczas wszystkie 4-krotne obserwacje (t = 0,1,2,3) dla tej osoby powinny zostać przypisane do próbki.

Poniższa linia robi prawie co chcę:

df_sample = df_data.loc[np.random.randint(3, size=100).tolist()] 

jednak nie spróbować osobnika wielokrotnie. Jeśli więc utworzona lista zmiennych losowych to [2, 3, 2, 4, 1, ...], wówczas trzecia osoba (indeks = 2 to trzecia osoba) jest wybrana tylko raz, a nie dwa razy w próbce losowej. Oznacza to, że jak tylko losowy wektor powyżej zawiera tę samą osobę więcej niż raz, w losowej próbce kończę z mniej niż 100 osobnikami (z 4 obserwacjami czasowymi). Próbowałem także funkcji df_data.sample, ale nie wydaje mi się być w stanie obsłużyć określonego wielopoziomowego indeksu mam tutaj w panelu. Mógłbym napisać różnego rodzaju pętle, aby to zrobić, ale myślałem, że powinien być prostszy (i szybszy) sposób robienia tego. Jestem na Pythonie 3.5 i używam wersji Pand w wersji 0.17.1. Dzięki.

+0

Możliwy duplikat [Jak dostać losowy (Bootstrap) próbki z pandas multiindex] (http://stackoverflow.com/questions/38731858/how-to-get-a-random-bootstrap-sample-from-pandas-multiindex) – maxymoo

Odpowiedz

1

Można użyć itertools.product szybko produkować formatu potrzebne, aby wybrać z duplikatów z MultiIndex: dane

Sample:

from itertools import product 
individuals = list(range(500)) 
time = (0, 1, 2, 3,) 
index = pd.MultiIndex.from_tuples(list(product(individuals, time))) 
df = pd.DataFrame(data={'A': np.random.random(size=2000), 'B': np.random.random(size=2000)}, index=index) 

       A   B 
0 0 0.208461 0.842118 
    1 0.481681 0.096121 
    2 0.420538 0.922363 
    3 0.859182 0.078940 
1 0 0.171162 0.255883 
    1 0.338864 0.975492 
    2 0.270533 0.504605 
    3 0.691041 0.709189 
2 0 0.220405 0.925001 
    1 0.811951 0.479795 
    2 0.010527 0.534866 
    3 0.561204 0.915972 
3 0 0.813726 0.083478 
    1 0.745100 0.462120 
    2 0.189111 0.552039 
    3 0.006141 0.622969 

Kombajny wynik np.random.randint z wartościami time użyciu product:

sample_ix = np.random.randint(low=0, high=500, size=100) 

len(np.unique(sample_ix)) 

91 

sample_multi_ix = list(product(sample_ix, time)) 

[(55, 0), (55, 1), (55, 2), (55, 3), (254, 0), (254, 1), (254, 2), (254, 3), ...] 

i wybierz odpowiednio:

sample = df.loc[sample_multi_ix, :] 
sample.info() 

MultiIndex: 400 entries, (55, 0) to (135, 3) 
Data columns (total 2 columns): 
A 400 non-null float64 
B 400 non-null float64 
dtypes: float64(2) 
memory usage: 9.4+ KB 

Jeśli chcesz unikalny sampleindex, można dodać:

sample.index = pd.MultiIndex.from_tuples(list(product(list(range(100)), time))) 

MultiIndex: 400 entries, (0, 0) to (99, 3) 
Data columns (total 2 columns): 
A 400 non-null float64 
B 400 non-null float64 
dtypes: float64(2) 
+0

Cześć Stefan, to świetne rozwiązanie i około 30 razy szybciej th to, co przygotowałem wczoraj wieczorem. Jedną rzeczą, którą należy dodać do swojego rozwiązania, jest ponowne zindeksowanie próbki, tak aby indeksy były ponownie unikalne, a niektóre funkcje pand można uruchomić na nim (np. OLS itp.). Coś takiego: 'individb = lista (zakres (100))' i 'indexb = pd.MultiIndex.from_tuples (lista (produkt (individualb, czas)))' i 'sample = sample.set_index (indexb)' –

+0

Nie ma za co, zaktualizowany, aby pozbyć się duplikatów w 'MultiIndex'. – Stefan

+0

Idealny. Dzięki. –

0

Proste rozwiązanie:

subindex = df.index.get_level_values('sub_index') 
sample_ids = np.random.choice(subindex, 5, replace=True) 
sample = df[subindex.isin(sample_ids)].copy() 
Powiązane problemy