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:
Je vous remercie! :)
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
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_
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)