web-dev-qa-db-fra.com

Échantillonnage stratifié dans les pandas

J'ai examiné les documents d'échantillonnage stratifié Sklearn ainsi que les documents dactylographiés pandas ainsi que des échantillons stratifiés de Pandas et un échantillonnage stratifié basé sur une colonne , mais ce n'est pas le cas. aborder cette question.

Je cherche un moyen rapide de générer un échantillon stratifié de taille n à partir d’un ensemble de données. Toutefois, pour les lignes dont le nombre d'échantillons est inférieur au nombre spécifié, toutes les entrées doivent être saisies.

Exemple concret:

enter image description here

Je vous remercie! :)

13
Wboy

Utilisez min lorsque vous passez le nombre à échantillonner. Considérons la dataframe df

df = pd.DataFrame(dict(
        A=[1, 1, 1, 2, 2, 2, 2, 3, 4, 4],
        B=range(10)
    ))

df.groupby('A', group_keys=False).apply(lambda x: x.sample(min(len(x), 2)))

   A  B
1  1  1
2  1  2
3  2  3
6  2  6
7  3  7
9  4  9
8  4  8
36
piRSquared

En élargissant la réponse groupby, nous pouvons nous assurer que l'échantillon est équilibré. Pour ce faire, lorsque pour toutes les classes le nombre d'échantillons est> = n_samples, nous pouvons simplement prendre n_samples pour toutes les classes (réponse précédente). Lorsque la classe minoritaire contient <n_samples, nous pouvons considérer que le nombre d'échantillons de toutes les classes est identique à celui de la classe minoritaire.

def stratified_sample_df(df, col, n_samples):
    n = min(n_samples, df[col].value_counts().min())
    df_ = df.groupby(col).apply(lambda x: x.sample(n))
    df_.index = df_.index.droplevel(0)
    return df_
1
Ilya Prokin

dans l'exemple suivant, un total de N lignes où chaque groupe apparaît dans sa proportion d'origine par rapport au nombre entier le plus proche, puis mélangez et réinitialisez l'index en utilisant:

df = pd.DataFrame(dict(
    A=[1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4],
    B=range(20)
))

Court et doux:

df.sample(n=N, weights='A', random_state=1).reset_index(drop=True)

Version longue

df.groupby('A', group_keys=False).apply(lambda x: x.sample(int(np.rint(N*len(x)/len(df))))).sample(frac=1).reset_index(drop=True)
0
irkinosor