Muestras estratificadas de pandas

Tengo un DataFrame de pandas que se ve aproximadamente de la siguiente manera:

cli_id | X1 | X2 | X3 | ... | Xn | Y | ---------------------------------------- 123 | 1 | A | XX | ... | 4 | 0.1 | 456 | 2 | B | XY | ... | 5 | 0.2 | 789 | 1 | B | XY | ... | 5 | 0.3 | 101 | 2 | A | XX | ... | 4 | 0.1 | ... 

Tengo ID de cliente, pocos atributos categóricos e Y, que es la probabilidad de un evento que tiene valores de 0 a 1 por 0.1.

Necesito tomar una muestra estratificada en cada grupo (por lo tanto, 10 pliegues) de Y de un tamaño de 200

A menudo lo uso para tomar una muestra estratificada al dividir en tren / prueba:

 def stratifiedSplit(X,y,size): sss = StratifiedShuffleSplit(y, n_iter=1, test_size=size, random_state=0) for train_index, test_index in sss: X_train, X_test = X.iloc[train_index], X.iloc[test_index] y_train, y_test = y.iloc[train_index], y.iloc[test_index] return X_train, X_test, y_train, y_test 

Pero no sé cómo modificarlo en este caso.

No estoy totalmente seguro de si te refieres a esto:

 strats = [] for k in range(11): y_val = k*0.1 dummy_df = your_df[your_df['Y'] == y_val] stats.append( dummy_df.sample(200) ) 

Eso hace un dataframe ficticio que consiste solo en los valores Y que desea, y luego toma una muestra de 200.

OK, así que necesitas que los diferentes trozos tengan la misma estructura. Supongo que eso es un poco más difícil, así es como lo haría:

En primer lugar, obtendría un histogtwig de cómo se ve X1 :

 hist, edges = np.histogram(your_df['X1'], bins=np.linespace(min_x, max_x, nbins)) 

Ahora tenemos un histogtwig con nbins bins.

Ahora la estrategia es dibujar un cierto número de filas dependiendo de cuál es su valor de X1 . Extraeremos más de los contenedores con más observaciones y menos de los contenedores con menos, de modo que se conserve la estructura de X

En particular, la contribución relativa de cada bin debe ser:

 rel = [float(i) / sum(hist) for i in hist] 

Esto será algo así como [0.1, 0.2, 0.1, 0.3, 0.3]

Si queremos 200 muestras, necesitamos dibujar:

 draws_in_bin = [int(i*200) for i in rel] 

Ahora sabemos cuántas observaciones sacar de cada contenedor:

 strats = [] for k in range(11): y_val = k*0.1 #get a dataframe for every value of Y dummy_df = your_df[your_df['Y'] == y_val] bin_strat = [] for left_edge, right_edge, n_draws in zip(edges[:-1], edges[1:], draws_in_bin): bin_df = dummy_df[ (dummy_df['X1']> left_edge) & (dummy_df['X1']< right_edge) ] bin_strat.append(bin_df.sample(n_draws)) # this takes the right number of draws out # of the X1 bin where we currently are # Note that every element of bin_strat is a dataframe # with a number of entries that corresponds to the # structure of draws_in_bin # #concatenate the dataframes for every bin and append to the list strats.append( pd.concat(bin_strat) ) 

Si el número de muestras es el mismo para cada grupo, o si la proporción es constante para cada grupo, podría intentar algo como

 df.groupby('Y').apply(lambda x: x.sample(n=200)) 

o

 df.groupby('Y').apply(lambda x: x.sample(frac=.1)) 

Para realizar un muestreo estratificado con respecto a más de una variable, simplemente agrupe con respecto a más variables. Puede ser necesario construir nuevas variables agrupadas para este fin.

Sin embargo, si el tamaño del grupo es demasiado pequeño en relación con la proporción de los tamaños de grupo 1 y propotion .25, no se devolverá ningún artículo. Esto se debe a la implementación redondeada por parte de los pitones de la función int(0.25)=0