2015-10-13 2 views
5

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

 
+------+-------+-------+ 
| col1 | clol2 | class | 
+------+-------+-------+ 
| 4 | 45 | A  | 
+------+-------+-------+ 
| 5 | 66 | B  | 
+------+-------+-------+ 
| 5 | 6  | C  | 
+------+-------+-------+ 
| 4 | 6  | C  | 
+------+-------+-------+ 
| 321 | 1  | A  | 
+------+-------+-------+ 
| 32 | 432 | B  | 
+------+-------+-------+ 
| 5 | 3  | B  | 
+------+-------+-------+ 

given a huge dataframe like above and the required frequency distribution like below: 
+-------+--------------+ 
| class | nostoextract | 
+-------+--------------+ 
| A  | 2   | 
+-------+--------------+ 
| B  | 2   | 
+-------+--------------+ 
| C  | 2   | 
+-------+--------------+ 


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

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

+1

Не могли бы вы привести примеры того, чего вы хотите достичь? И вы посмотрели на 'pandas.DataFrame.sample'? (Http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sample.html) –

+0

@ chris-sc да, это не позволяет пробовать на основе столбца класса – stackit

+0

В основном я хочу пробовать перекошенный фрейм данных, чтобы все метки классов были достаточно представлены как можно больше. Ярлыки классов находятся в столбце «label». Это подается в классификатор. @ chris-sc – stackit

ответ

3

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

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 

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

+0

спасибо, может быть, так же можно сделать для sframe? (graphlab – stackit

+0

@stackit, dunno ... у них, похоже, один и тот же интерфейс. Вы попробовали? – swenzel

4

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

т.е.

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

Тогда, как только вы разделить/создать/фильтруется на DFA, DFB, DFC, выбрать номер из верхней по желанию (если dataframes не имеют какой-либо конкретной сортировки-шаблон)

dfasamplefive = dfa[:5] 

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

dfasamplefive = dfa.sample(n=5) 

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

+1

должен быть dfasamplefive = dfa [: 5], если вы хотите получить 5 лучших значений ... – PALEN

+0

Да, вы вполне Правильно, спасибо за это! [отредактировано соответствующим образом] –

1

Вот решение для фреймов. Это не точно, что вы хотите, потому что он выборочно отображает точки, так что результаты не обязательно имеют точно количество заданных строк. Точный метод, вероятно, случайным образом перетасовывает данные, а затем берет первые строки 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] 

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

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

спасибо, будет ли он также масштабироваться? – stackit

+0

Масштаб в каком виде? – papayawarrior

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