2017-01-25 4 views
0

Я использую панды, у меня есть набор данных с примерно 4 миллионами наблюдений. Мне было интересно, какой лучший/самый быстрый/самый эффективный способ выбрать 50 случайных элементов или первые 50 элементов для каждого класса (класс - это всего лишь столбец).Выбор n-элементов каждого класса

Уникальное количество классов в моем столбце около ~ 2k, и я хотел бы выбрать подмножество из 100 000 элементов, 50 элементов для каждого класса.

Я думал о том, чтобы сгруппировать их в класс, затем повторить каждую группу и выбрать первые 50 элементов, а затем перейти к следующей группе.

Мне было интересно, есть ли лучший способ сделать это?

ответ

1

Учитывая следующее dataframe

df = pd.DataFrame(np.random.rand(100, 2), columns=list('ab')) 
df['group'] = np.remainder(np.random.permutation(len(df)), 3) 

df.head() 

    a   b   group 
0 0.069140 0.553955 1 
1 0.564991 0.699645 2 
2 0.251304 0.516667 2 
3 0.962819 0.314219 2 
4 0.353382 0.500961 0 

вы можете получить рандомизированную версию,

df_randomized = df.ix[np.random.permutation(len(df))] 

df_randomized.head() 

    a   b   group 
90 0.734971 0.895469 0 
35 0.195013 0.566211 0 
27 0.370124 0.870052 2 
21 0.297194 0.500713 1 
66 0.319668 0.347365 2 

Для выбора N случайных элементов, первым генерировать перестановки и уменьшить его в размерах. После этого применить его к dataframe:

N = 10 
indexes = np.random.permutation(len(df))[:N] 
df_randomized = df.ix[indexes] 

Чтобы получить первые N элементов каждой группы вы можете сгруппировать dataframe и применить метод, чтобы выбрать первые N элементов. Нет необходимости в каких-либо петель здесь, как панды может справиться с этим для вас:

N = 10 
df.groupby('group')\ 
    .apply(lambda x: x[:N][['a', 'b']]) 

Все эти методы должны быть быстрыми, поскольку они используют внутренние оптимизированные методы либо NumPy или панд.

1

IIUC вам нужно использовать numpy.random.choice

import pandas as pd 
import numpy as np 

df = pd.DataFrame({'class': [0,1,2,3,0,1,2,3,0,1,2,3], 
       'value': [1,2,3,4,5,6,7,8,9,10,1,12]}) 


Samplesize = 2 #number of samples that you want  
print df.groupby('class', as_index=False).apply(lambda array: array.loc[np.random.choice(array.index, Samplesize, False),:]) 

вход

class value 
0  0  1 
1  1  2 
2  2  3 
3  3  4 
4  0  5 
5  1  6 
6  2  7 
7  3  8 
8  0  9 
9  1  10 
10  2  1 
11  3  12 

выход

 class value 
0 8  0  9 
    0  0  1 
1 1  1  2 
    5  1  6 
2 6  2  7 
    10  2  1 
3 11  3  12 
    3  3  4 
+0

Спасибо за ваш ответ, но когда у меня есть класс с числом наблюдений, который меньше моего указанного Samplesize, я не могу использовать это решение. Im, происходящее в ValueError: не может взять более крупный образец, чем население, когда «replace = False» – sebb

+0

print df.groupby ('class', as_index = False) .apply (лямбда-массив: array.loc [np.random.choice (array.index) , Samplesize, True) ,:]) используйте этот, просто помните, что образец может иметь дубликаты, если он равен True – Shijo

+0

@sebb Вы сказали, что хотите 50 элементов каждого класса. Если у класса есть менее 50 элементов, вы не можете этого сделать, поэтому повышение исключения выглядит правильно. – Goyo

Смежные вопросы