Sélection aléatoire de lignes dans la trame de données Pandas


159

Existe-t-il un moyen de sélectionner des lignes aléatoires à partir d'un DataFrame dans Pandas.

Dans R, en utilisant le package voiture, il existe une fonction utile some(x, n)qui est similaire à head mais qui sélectionne, dans cet exemple, 10 lignes au hasard à partir de x.

J'ai également regardé la documentation de découpage et il ne semble y avoir rien d'équivalent.

Mettre à jour

Utilisant maintenant la version 20. Il existe un exemple de méthode.

df.sample(n)


1
Si vous cherchez à échantillonner où la taille est supérieure à l'original, utilisez df.sample(N, replace=True). Plus de détails ici .
cs95

Réponses:


57

Quelque chose comme ça?

import random

def some(x, n):
    return x.ix[random.sample(x.index, n)]

Remarque: Depuis Pandas v0.20.0, ix a été déconseillée au profit de l' locindexation basée sur les étiquettes.


8
Merci @eumiro. J'ai également pensé que df.ix[np.random.random_integers(0, len(df), 10)]cela fonctionnerait également.
John

7
Si vous souhaitez utiliser numpy, vous pouvez également le faire df.ix[np.random.choice(df.index, 10)].
naught101

7
Quelqu'un dans un autre message a mentionné que np.random.choicec'était deux fois plus rapide querandom.sample
Phani

5
Si vous utilisez np.random.choice, vous devez spécifier replace = False, sinon vous obtiendrez des lignes en double!
stmax

2
Je pense que ".ix" est obsolète et que vous devriez utiliser .loc pour l'indexation basée sur les étiquettes
compguy24

266

Avec la version pandas 0.16.1et les versions ultérieures, il existe maintenant une DataFrame.sample méthode intégrée :

import pandas

df = pandas.DataFrame(pandas.np.random.random(100))

# Randomly sample 70% of your dataframe
df_percent = df.sample(frac=0.7)

# Randomly sample 7 elements from your dataframe
df_elements = df.sample(n=7)

Pour l'une ou l'autre approche ci-dessus, vous pouvez obtenir le reste des lignes en faisant:

df_rest = df.loc[~df.index.isin(df_percent.index)]

df_0.7n'est pas un nom valide. De plus, je suggère de remplacer df_rest = df.loc[~df.index.isin(df_0_7.index)]par df_rest = df.loc[df.index.difference(df_0_7.index)].
Pietro Battiston

@PietroBattiston Merci. J'essayais de clarifier la réponse, mais je conviens qu'un exemple qui ne fonctionne pas n'est pas clair. Bien avec le pourboire sur la différence. Cependant, je préfère toujours écrire le slicing pour que je le lise comme des indices "pas dans l'index de mon échantillon". Y a-t-il une augmentation des performances avec difference()?
ryanjdillon

1
@ryanjdillon il restait une faute de frappe, je l'ai corrigée. Concernant la méthode, je reprends en fait ma suggestion, car en effet c'est un peu moins efficace. df_percent.index.get_indexer(df.index) == -1est bien plus efficace à la place (mais aussi plus moche) ...
Pietro Battiston

18

sample

À partir de la v0.20.0, vous pouvez utiliser pd.DataFrame.sample, qui peut être utilisé pour renvoyer un échantillon aléatoire d'un nombre fixe de lignes, ou un pourcentage de lignes:

df = df.sample(n=k)     # k rows
df = df.sample(frac=k)  # int(len(df.index) * k) rows

Pour la reproductibilité, vous pouvez spécifier un entier random_state, équivalent à utiliser np.ramdom.seed. Ainsi, au lieu de définir, par exemple np.random.seed = 0, vous pouvez:

df = df.sample(n=k, random_state=0)

7

La meilleure façon de le faire est d'utiliser la fonction exemple du module aléatoire,

import numpy as np
import pandas as pd
from random import sample

# given data frame df

# create random index
rindex =  np.array(sample(xrange(len(df)), 10))

# get 10 random rows from df
dfr = df.ix[rindex]

4

En fait, cela vous donnera des indices répétés np.random.random_integers(0, len(df), N)Nest un grand nombre.


3

La ligne ci-dessous sélectionnera au hasard n nombre de lignes sur le nombre total de lignes existantes de la trame de données df sans remplacement.

df=df.take(np.random.permutation(len(df))[:n])

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.