2015-10-13 10 views
5

Jak mogę próbkować ramkę danych pandy lub graficzną ramkę sb na podstawie danej klasy \ wartości rozkładu etykiety np. Chcę próbkować ramkę danych z kolumną label \ class, aby wybrać wiersze takie, każda etykieta klasy jest równie pobierana, dzięki czemu ma podobną częstotliwość dla każdej etykiety klasy, co odpowiada jednolitemu rozkładowi etykiet klasy. Najlepiej byłoby pobrać próbki zgodnie z pożądanym rozkładem klas.Próbkowanie frameworka opartego na danym rozkładzie

 
+------+-------+-------+ 
| 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   | 
+-------+--------------+ 


Powyższe należy wyodrębnić wiersze od pierwszego dataframe na podstawie danego rozkładu częstotliwości w drugiej ramce, gdy wartość licznika częstotliwości podano w nostoextract kolumnę z wytworzeniem próbkowanego ramki, gdzie każda grupa pojawia się maksymalnie 2 razy. powinien zignorować i kontynuować, jeśli nie może znaleźć wystarczającej liczby klas, aby spełnić wymaganą liczbę. Wynikowa ramka danych ma być używana dla klasyfikatora opartego na drzewach decyzyjnych.

Jak komentator podaje, próbkowana ramka danych musi zawierać nostoextract różne instancje odpowiedniej klasy? O ile nie ma wystarczającej liczby przykładów dla danej klasy, w takim przypadku po prostu weź wszystkie dostępne.

+1

Czy możesz dodać przykłady tego, co chcesz osiągnąć? A czy patrzysz na 'pandas.DataFrame.sample'? (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sample.html) –

+0

@ chris-sc tak nie pozwala na próbkowanie na podstawie kolumny klasy – stackit

+0

zasadniczo chcę wypróbować przekrzywioną ramkę danych tak, aby wszystkie etykiety klas były w wystarczającym stopniu reprezentowane tak dużo jak to możliwe. Etykiety klas znajdują się w kolumnie "etykieta". To jest podawane do klasyfikatora. @ chris-sc – stackit

Odpowiedz

3

myślę, że to rozwiąże problem:

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)) 

Drukuje:

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 

Jeśli nie chcesz, aby wynik zamawiane przez klas, można permute go w końcu.

+0

dzięki, czy to samo można zrobić dla sframe? (graphlab – stackit

+0

@stackit, dunno ... wydają się mieć ten sam interfejs.) Wypróbowałeś? – swenzel

4

Czy dzielisz swoją pierwszą ramkę danych na pod-dane ramek specyficzne dla klasy, a następnie próbkujesz z nich?

tj

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

Potem kiedy już Split/utworzone/filtrowane na DFA, DFB, DFC, wybrać numer z góry jako pożądanego (jeśli dataframes nie mają żadnego konkretnego sortowania-wzór)

dfasamplefive = dfa[:5] 

Albo użyć metody przykładowy sposób opisany przez poprzedniego commenter do bezpośredniego podjęcia próby losowej:

dfasamplefive = dfa.sample(n=5) 

Jeśli to pasuje do twoich potrzeb, wszystko, co pozostało do zrobienia, to zautomatyzować proces, podając liczbę, która ma być próbkowana z kontrolnej ramki danych, którą masz jako drugą ramkę danych zawierającą żądaną liczbę próbek.

+1

powinien być dfasamplefive = dfa [: 5] jeśli chcesz mieć 5 najlepszych wartości ... – PALEN

+0

Tak, jesteś całkiem racja, dzięki za to! [edytuj odpowiednio] –

1

Oto rozwiązanie dla SFrames. Nie jest to dokładnie to, czego potrzebujesz, ponieważ pobiera próbki losowo, więc wyniki niekoniecznie muszą mieć dokładnie określoną liczbę wierszy. Dokładna metoda prawdopodobnie losowo przetasuje dane, a następnie pobierze pierwsze wiersze k dla danej klasy, ale to spowoduje, że będziesz bardzo blisko.

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] 

Podczas mojego próbnego uruchomienia, zdarzyło mi się uzyskać dokładną liczbę próbek, które podałem, ale to nie gwarantuje tego rozwiązania.

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

dziękuję też będzie skalować? – stackit

+0

Skala w jaki sposób? – papayawarrior

Powiązane problemy