Выборка данных на основе данных распределений

Как я могу пробовать фрейм данных pandas или graphlab sframe на основе заданных значений распределения классов \ label: например, я хочу, чтобы образец кадра данных имел столбец label \ class, чтобы выбрать строки, чтобы каждый классный ярлык был одинаково выбран, тем самым имея аналогичную частоту для каждой метки класса, соответствующей равномерному распределению меток классов. Или лучше всего получить образцы в соответствии с распределением классов, которое мы хотим.

 + ------ + ------- + ------- +
 |  col1 |  clol2 |  класс |
 + ------ + ------- + ------- +
 |  4 |  45 |  A |
 + ------ + ------- + ------- +
 |  5 |  66 |  B |
 + ------ + ------- + ------- +
 |  5 |  6 |  C |
 + ------ + ------- + ------- +
 |  4 |  6 |  C |
 + ------ + ------- + ------- +
 |  321 |  1 |  A |
 + ------ + ------- + ------- +
 |  32 |  432 |  B |
 + ------ + ------- + ------- +
 |  5 |  3 |  B |
 + ------ + ------- + ------- +

 учитывая огромный формат данных, как указано выше, и требуемое распределение частот, как показано ниже:
 + ------- + -------------- +
 |  класс |  nostoextract |
 + ------- + -------------- +
 |  A |  2 |
 + ------- + -------------- +
 |  B |  2 |
 + ------- + -------------- +
 |  C |  2 |
 + ------- + -------------- +


Вышеизложенное должно извлекать строки из первого фрейма данных на основе заданного распределения частоты во втором кадре, где значения счетчика частоты задаются в столбце nostoextract, чтобы получить дискретный кадр, где каждый класс отображается максимум 2 раза. следует игнорировать и продолжать, если не найти достаточные классы для соответствия требуемому счету. Результирующий фрейм данных должен использоваться для классификатора на основе дерева решений.

Как отмечает комментатор, дискретный фреймворк должен содержать nostoextract для разных экземпляров соответствующего класса? Если не хватает примеров для данного класса, в этом случае вы просто берете все доступные.

    Можете ли вы разбить первый фрейм данных на подкадры данных класса, а затем попробовать по желанию?

    т.е.

     dfa = df[df['class']=='A'] dfb = df[df['class']=='B'] dfc = df[df['class']=='C'] .... 

    Затем, как только вы разделите / создали / отфильтровали на dfa, dfb, dfc, выберите число сверху (если в данных нет определенного шаблона сортировки)

      dfasamplefive = dfa[5:] 

    Или используйте метод образца, как описано предыдущим комментатором, чтобы непосредственно взять произвольную выборку:

     dfasamplefive = dfa.sample(n=5) 

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

    Я думаю, что это решит вашу проблему:

     import pandas as pd data = pd.DataFrame({'cols1':[4, 5, 5, 4, 321, 32, 5], 'clol2':[45, 66, 6, 6, 1, 432, 3], 'class':['A', 'B', 'C', 'C', 'A', 'B', 'B']}) freq = pd.DataFrame({'class':['A', 'B', 'C'], 'nostoextract':[2, 2, 2], }) def bootstrap(data, freq): freq = freq.set_index('class') # This function will be applied on each group of instances of the same # class in `data`. def sampleClass(classgroup): cls = classgroup['class'].iloc[0] nDesired = freq.nostoextract[cls] nRows = len(classgroup) nSamples = min(nRows, nDesired) return classgroup.sample(nSamples) samples = data.groupby('class').apply(sampleClass) # If you want a new index with ascending values # samples.index = range(len(samples)) # If you want an index which is equal to the row in `data` where the sample # came from samples.index = samples.index.get_level_values(1) # If you don't change it then you'll have a multiindex with level 0 # being the class and level 1 being the row in `data` where # the sample came from. return samples print(bootstrap(data,freq)) 

    Печать:

      class clol2 cols1 0 A 45 4 4 A 1 321 1 B 66 5 5 B 432 32 3 C 6 4 2 C 6 5 

    Если вы не хотите, чтобы результат был упорядочен по классам, вы можете переставить его в конце.

    Вот решение для SFrames. Это не совсем то , что вы хотите, потому что оно выборочно отображает точки, так что результаты не обязательно имеют точно количество строк, которые вы указали. Точный метод, вероятно, случайным образом перетасовал бы данные, а затем взял первые k строк для данного класса, но это поможет вам приблизиться.

     import random import graphlab as gl ## Construct data. sf = gl.SFrame({'col1': [4, 5, 5, 4, 321, 32, 5], 'col2': [45, 66, 6, 6, 1, 432, 3], 'class': ['A', 'B', 'C', 'C', 'A', 'B', 'B']}) freq = gl.SFrame({'class': ['A', 'B', 'C'], 'number': [3, 1, 0]}) ## Count how many instances of each class and compute a sampling # probability. grp = sf.groupby('class', gl.aggregate.COUNT) freq = freq.join(grp, on ='class', how='left') freq['prob'] = freq.apply(lambda x: float(x['number']) / x['Count']) ## Join the sampling probability back to the original data. sf = sf.join(freq[['class', 'prob']], on='class', how='left') ## Sample the original data, then subset. sf['sample_mask'] = sf.apply(lambda x: 1 if random.random() <= x['prob'] else 0) sf2 = sf[sf['sample_mask'] == 1] 

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

     >>> sf2 +-------+------+------+ | class | col1 | col2 | +-------+------+------+ | A | 4 | 45 | | A | 321 | 1 | | B | 32 | 432 | +-------+------+------+