2012-08-30 22 views
62

Sto cercando di leggere un file CSV abbastanza grande con Panda e suddividerlo in due blocchi casuali, uno dei quali è il 10% dei dati e l'altro è il 90%.Panda: campionamento di un DataFrame

Ecco il mio tentativo attuale:

rows = data.index 
row_count = len(rows) 
random.shuffle(list(rows)) 

data.reindex(rows) 

training_data = data[row_count // 10:] 
testing_data = data[:row_count // 10] 

Per qualche ragione, sklearn getta questo errore quando provo ad usare uno di questi oggetti dataframe risultanti all'interno di un classificatore SVM:

IndexError: each subindex must be either a slice, an integer, Ellipsis, or newaxis 

penso Sto sbagliando. C'è un modo migliore per farlo?

+3

Per inciso, questo non sarebbe casuale mescolare in modo corretto in ogni caso - il problema è 'random.shuffle (elenco (righe))' . 'shuffle' altera i dati su cui opera, ma quando chiamate' list (rows) ', fate una copia di' rows' che viene alterata e poi gettata via - la serie di panda sottostante, 'rows', è invariata. Una soluzione è chiamare 'rows = list (rows)', quindi 'random.shuffle (rows)' e 'data.reindex (rows)' dopo. –

risposta

76

Quale versione di panda stai usando? Per me il tuo codice funziona bene (sono su Git Master).

Un altro approccio potrebbe essere:

In [117]: import pandas 

In [118]: import random 

In [119]: df = pandas.DataFrame(np.random.randn(100, 4), columns=list('ABCD')) 

In [120]: rows = random.sample(df.index, 10) 

In [121]: df_10 = df.ix[rows] 

In [122]: df_90 = df.drop(rows) 

più recente versione (da 0.16.1 a) sostiene questa direttamente: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sample.html

+7

Un altro approccio è usare 'np.random.permuation' –

+1

@WesMcKinney: ho notato che' np.random.permutation' eliminerebbe i nomi delle colonne da DataFrame, perché 'np.random.permutation'. Esiste un metodo in panda che rimescoli il dataframe mentre conserva i nomi delle colonne? – hlin117

+4

@hlin df.loc [np.random.permutation (df.index)] mescola il dataframe e mantiene i nomi delle colonne. –

77

Ho scoperto che np.random.choice() nuovo in NumPy 1.7.0 funziona abbastanza bene per Questo.

Ad esempio, è possibile passare i valori dell'indice da un DataFrame e il numero intero 10 per selezionare 10 righe casuali campionate in modo uniforme.

rows = np.random.choice(df.index.values, 10) 
sampled_df = df.ix[rows] 
+0

con ipitone timeit ci vuole la metà del tempo 'random.sample' .. impressionante – gc5

+0

+1 per l'uso di np.random.choice. Inoltre, se hai un 'pd.Series' di probabilità,' prob', puoi scegliere dall'indice in questo modo: 'np.random.choice (prob.index.values, p = prob.values)' – LondonRob

+37

Don ' t dimenticare di specificare replace = False se si desidera il campionamento senza sostituzione.In caso contrario, questo metodo può potenzialmente campionare la stessa riga più volte. –

13

Panda 0.16.1 avere un metodo sample per quello.

+0

Bello! Ma devi ancora caricare tutti i dati in memoria, giusto? – Nikolay

+0

Lo faccio dopo aver caricato i dati in memoria. – hurrial

17

Nuovo nella versione 0.16.1:

sample_dataframe = your_dataframe.sample(n=how_many_rows_you_want) 

doc qui: http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.DataFrame.sample.html

+0

Una volta che hai il tuo sample_dataframe, come lo sottrai da your_dataframe? –

+0

@ChrisNielsen Stai chiedendo in modo da poter eseguire la convalida incrociata? In tal caso, consiglio http://scikit-learn.org/stable/modules/cross_validation.html perché ti fornisce tutti i tuoi set di dati di addestramento e test (X_train, X_test, y_train, y_test) direttamente – dval