2016-01-20 3 views
6

Я работаю со следующими данными панели в MultiIndex пандах DataFrame называемых df_data:Отбор пробы из мультииндексного 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 индексы физического лица (есть 500 из них), t индексов времени. Это сбалансированная панель. Я хотел бы создать случайный образец nn=100 особей с заменой. Кроме того, если индивид превращает его в случайную выборку, все четыре временных наблюдения (t = 0,1,2,3) для этого человека должны быть отнесены к образцу.

Следующая строка делает почти то, что я хочу:

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

Однако, это не образец индивидуума неоднократно. Поэтому, если созданный список случайных величин, скажем, [2, 3, 2, 4, 1, ...], то третий индивидуум (индекс = 2 является третьим индивидуумом) выбирается только один раз, а не дважды в случайную выборку. Это означает, что, как только случайный вектор выше содержит одного и того же человека более одного раза, я получаю менее 100 человек (с 4 наблюдениями времени каждый) в случайной выборке. Я также пробовал функцию df_data.sample, но, похоже, я не могу справиться с конкретным многоуровневым индексом, который у меня здесь, на панели. Я мог написать все виды циклов, чтобы это сделать, но я думал, что должен быть более простой (и более быстрый) способ сделать это. Я на Python 3.5, и я использую версию pandas 0.17.1. Спасибо.

+0

Возможный дубликат [Как получить случайную (Bootstrap) образца из pandas multiindex] (http://stackoverflow.com/questions/38731858/how-to-get-a-random-bootstrap-sample-from-pandas-multiindex) – maxymoo

ответ

1

Вы можете использовать itertools.product быстро производить формат, необходимый для выбора дубликатов из MultiIndex в:

Образец данных:

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 

Объединить результат np.random.randint с time значений с помощью 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), ...] 

и выберите соответственно:

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 

Если вы хотите уникальный sampleindex, вы можете добавить:

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

Привет, Стефан, это отличное решение и примерно в 30 раз быстрее го что я приготовил прошлой ночью. Одно, что добавить к вашему решению, - это переиндексировать образец, чтобы индексы были уникальными снова, и некоторые функции pandas могут быть запущены на нем (например, OLS и т. Д.). Что-то вроде этого: 'individualb = list (range (100))' и 'indexb = pd.MultiIndex.from_tuples (список (продукт (индивидуалы, время)))' и 'sample = sample.set_index (indexb)' –

+0

Пожалуйста, обновите, чтобы избавиться от обмана в «MultiIndex». – Stefan

+0

Perfect. Благодарю. –

0

Простое решение:

subindex = df.index.get_level_values('sub_index') 
sample_ids = np.random.choice(subindex, 5, replace=True) 
sample = df[subindex.isin(sample_ids)].copy() 
Смежные вопросы