> Modules non standards > Pandas > Création de Series
Création de Series
Création d'une série, c'est à dire d'un vecteur de valeurs d'une variable (en général valeurs pour différents individus) :
- s = pandas.Series([1, 2, 5, 7]) : série numérique entière.
- s = pandas.Series([1.3, 2, 5.3, 7]) : série numérique flottante.
- s = pandas.Series([1, 2, 5, 7], dtype = float) : série numérique flottante.
- on peut utiliser comme type les types numpy, par exemple : s = pandas.Series([1, 2, 5, 7], dtype = numpy.int8)
- on peut mettre la valeur numpy.nan pour les valeurs non déterminées (qui apparaît alors comme NaN).
- len(s) ou s.size : taille de la série.
Variables de type catégorie :
- s = pandas.Series(['a', 'b', 'a', 'a', 'c'], dtype = 'category') : création d'une variable de type catégorie.
- s = pandas.Categorical(['a', 'b', 'a', 'a', 'c'], categories = ['c', 'b', 'a'], ordered = True) : variable de type catégorie, déclarée comme ordonnée (le défaut est False). Le type de s est alors CategoricalDtype(categories=['c', 'b', 'a'], ordered=True)
- df['A'] = df['A'].astype('category') : conversion d'une colonne en catégorie.
Si
s = pandas.Series([1, 5, 3, 9, numpy.inf, numpy.nan]) :
- s[s < 5] = 99 : met à 99 les valeurs inférieures à 5
- s[s == numpy.inf] = 99 : met à 99 les valeurs infinies.
- s[numpy.isnan(s)] = 99 : met à 99 les valeurs nan (attention : s[s == numpy.nan] = 99 ne marche pas, car numpy.nan == numpy.nan est False !)
s2 = s.copy() : fait une copie indépendante de la série.
Modification de valeurs :
- on peut faire s.replace({'a': 'A', 'b': 'B'}) : remplace les 'a' par des 'A' et 'b' par des 'B' et renvoie une série modifiée.
- on peut aussi faire s.map({'a': 'A', 'b': 'B'}), mais les valeurs non présentes dans le dictionaire seront mises à NaN
- on peut aussi donner une fonction à map : s.map(lambda x: 'A' if x == 'a' else 'B' if x == 'b' else numpy.nan)
Index d'une série : c'est le nom affecté à chaque valeur :
- pandas.Series([1, 2, 5, 7], index = ['a', 'b', 'c', 'd']) : permet de donner des noms aux individus (i.e. à chaque valeur).
- pour donner des noms, on peut aussi utiliser un dictionnaire : pandas.Series({'a': 1, 'b': 2, 'c': 5, 'd': 7}) revient au même que l'exemple juste au-dessus (si on donne un dictionnaire, les éléments sont triés par ordre alphabétique des clefs).
- l'index par défaut est [0, ..., n-1]
- mySerie.index : renvoie l'index d'une série qui est de la classe Index.
- on peut réindexer une série : dans le cas précédent, s.reindex(['c', 'b', 'a', 'e']) renvoie la série (5, 2, 1, NaN) (car par de valeur associée à l'index 'e').
s.describe() : valeurs statistiques d'une série.
Création d'une série avec valeur répétée :
- pandas.Series(0, index = range(5)) : série avec cinq 0.
- pandas.Series(0, range(5)) : série avec cinq 0.
Indexation des séries :
- une série se comporte de façon très similaire à une array numpy et aussi un dictionnaire.
- pour une série avec des valeurs d'index définies comme s = pandas.Series([2, 5, 7, 3], index = ['a', 'b', 'c', 'd'])
on peut accéder à une valeur par valeur d'index :
- s['b'] ou s.at['b'] ou s.loc['b'] ou s.get('b')
- la forme avec get renvoie None si le nom n'existe pas, alors que les autres formes lèvent une exception.
- on peut tester l'existence d'un nom avec : 'b' in s
- on peut accéder à une valeur par numéro (origine à 0) :
- s[0] ou s.iat[0] ou s.iloc[0] ou s.get(0)
- la forme avec get renvoie None si le nom n'existe pas, alors que les autres formes lèvent une exception.
- attention, avec les formes s[0] et s.get(0) :
- si 0 fait partie des valeurs d'index, renvoie la valeur correspondante pour cette valeur d'index.
- si 0 ne fait pas partie des valeurs index, renvoie la première valeur (valeur pour le numéro d'ordre).
- iat, at, iloc et loc ne sont pas ambigus
- se rappeler que si l'on n'a pas défini un index explicitement, il existe quand même (et vaut range(len(s))).
- s[[0, 2, 3]] : valeurs pour les indices donnés, avec les même problèmes d'ambiguité que ci-dessus sur les indices, selon qu'ils sont numériques ou non.
- s[2:4] : renvoie une série avec les valeurs des indices 2 à 4 exclus, mais cette-fois, ce sont bien des indices de ligne !
- s.iloc[1] : utilisation des numéros de lignes (origine à 0) sans ambiguité !
- s.iloc[[1, 3]] : utilisation des numéros de lignes (origine à 0) sans ambiguité et renvoie une série.
- s.iloc[1:3] : avec un range sur les numéros de lignes (origine à 0) sans ambiguité et renvoie une série.
Indexation de sous-séries : attention, quand on a extrait une sous-série avec par exemple s = s[s > 4], les numéros d'index n'ont pas changé ! (s[1] pointe toujours vers la même valeur qu'avant s'il fait toujours partie de la série, sinon, exception).
Opérations sur les séries : on peut utiliser les opérations comme sur les array numpy :
- s + s
- s * 2
- s + 1
- numpy.log(s); numpy.floor(s) : ça redonne une series
- les opérations alignent sur les index :
s1 = pandas.Series([1, 2, 3], ['a', 'b', 'c'])
s2 = pandas.Series([4, 5, 6], ['a', 'd', 'c'])
s1 + s2
donne :
a 5
b NaN
c 9
d NaN
les index seulement présents dans l'un des deux donnent NaN.
on peut éliminer les lignes avec NaN par : (s1 + s2).dropna()
Minimum élément par élément de 2 séries :
- numpy.minimum(s1, s2)
- on peut aussi faire un dataframe avec les 2 séries, puis prendre le minimum par ligne : pandas.concat([s1, s2], axis = 1).min(axis = 1)
Attribut name d'une série :
- on peut attribuer un nom à une série : s = pandas.Series([2, 5, 7, 3], index = ['a', 'b', 'c', 'd'], name = 'val')
- on peut changer ce nom : s.name = 'val2' ou s.rename('val2')
Concaténation de series de type string, ici séparées par des tirets : s1 + '-' + s2 + '-' + s3
Pour une série :
- s.values : donne les valeurs sous forme d'array numpy.
- s.unique() : donne les valeurs uniques sous forme d'array numpy.
Elimination des NaN :
- avec series : s[~ numpy.isnan(s)] et s[- numpy.isnan(s)] marchent tous les deux pour éliminer les NaN
- avec array numpy : ar[~ numpy.isnan(ar)] marche seulement et s[- numpy.isnan(s)] marchent tous les deux pour éliminer les NaN
Pour des séries, si
s1 = pandas.Series([1, 2, 3, numpy.nan]) et
s2 = pandas.Series([1, 4, 3, 6])
- s1.isna() ou s1.isnull() : renvoie une série booléenne indiquant les valeurs nan (ces 2 fonctions sont exactement la même chose)
- s1.notna() ou s1.notnull() : renvoie une série booléenne indiquant les valeurs non nan.
- s.min(), s.max(), s.mean(), s.median(), s.sum(), s.mad() : les valeurs correspondantes.
- (s1 == s2).all() : teste si toutes les valeurs sont égales.
- (s1 == s2).any() : teste s'il y une position où les valeurs sont égales.
- s.sort_index() : renvoie la série triée par valeurs des index.
- s.sort_values() : renvoie la série triée par valeurs croissantes (les nan sont en dernier, mais on peut les mettre en premier en donnant l'option na_position = 'first').
- s.sort_values(ascending = False) : tri par ordre décroissant.
- s2.idxmax() : renvoie l'index correspondant à la valeur maximale, donc ici 1 (idem avec idxmin).
- s2.apply(lambda x: 2 * x + 1) : renvoie le résultat de l'application de la fonction
- s1.corr(s2) : corrélation de pearson. En fait, on peut faire s1.corr(s2, method = 'pearson'), mais aussi avec method = 'kendall' ou method = 'spearman'.
Attention : l'opérateur in pour une série ne teste pas l'appartenance à la série, mais à son index ! Si
s = pandas.Series(['a', 'b', 'c']) :
- 'a' in s : donne False
- 1 in s : donne True
- 'a' in s.values : donne True
Fonction isin : si s = pandas.Series(['a', 'b', 'c']), s.isin(['a', 'c', 'x']) teste si chaque élément de la série est ou non dans la liste donnée (donc renvoie ici la Series [True, False, True]).
Test pour les NaN :
- pandas.isnull(x) : renvoie True si x est NaN (numpy.nan ou None)
- pandas.notnull(x) : renvoie False si x est numpy.nan ou None
pour déterminer le numéro d'ordre de chaque valeur (rank) :
- s1.rank() : renvoie les numéros d'ordre pour chaque valeur, dans l'ordre croissant. Si des valeurs sont identiques, attribue à toutes ces valeurs la moyenne des rangs possibles. Si 2 valeurs identiques pour les rangs 2 et 3, leur attribue 2.5 à toutes les deux (le champ method vaut 'average' par défaut).
- s1.rank(method = 'min') : renvoie aussi les numéros d'ordre de chaque valeur (numéros entre 1 et n), mais en cas de valeurs identiques, donne le rang minimum, puis saute au suivant. Par exemple, si 2 valeurs identiques pour les rangs 2 et 3, leur attribue 2 à toutes les deux, puis saute au rang 4.
- s1.rank(method = 'first') : idem, mais en cas de valeurs identiques, les classe dans l'ordre initial. Par exemple, si 2 valeurs identiques pour les rangs 2 et 3, la première aura le rang 2 et la seconde le rang 3.
- s1.rank(ascending = False) : renvoie les numéros d'ordre dans l'ordre décroissant (défaut est ascending = True).
s1.argsort() : renvoie les index dans l'ordre croissant des valeurs (de telle sorte que s1[s1.argsort()] est trié par ordre croissant). Attention : ce ne sont pas les numéros d'ordre pour chaque valeur, utiliser rank pour cela !
Fonctions vectorisées sur une série contenant des chaînes de caractères :
- accès se fait via le champ str. Par exemple, s.str.startswith('a') : renvoie une série de booléens (idem avec endswith)
- s.str.len() : renvoie une série avec les longueurs des chaînes.
- s.str.lower : convertit en minuscule (idem avec upper pour majuscules).
- df['A'].str.match('^[1-9]') : renvoie une série de booléens qui indique si chaque élément matche, mais le match doit se faire au début !
- df['A'].str.contains('^[1-9]') : renvoie une série de booléens qui indique si chaque élément matche (n'importe où)
- df['A'].str.contains('*', regex = False) : renvoie une série de booléens qui indique si chaque élément contient la chaîne indiquée.
- df['A'].str.find('ab') : retourne pour chaque élément l'index de la première ocurrence de 'ab', ou -1 si pas trouvé.
- df['A'].str.get(2) : retourne le 3ème caractère de chaque élément (ou NaN si n'existe pas).
- récupération d'une substring d'une colonne : df['A'].str.slice(0,5) ou même df['A'].str[0:5]
- s.str.count('(\w)(\d)') : renvoie une série numérique indiquant le nombre de match avec le pattern de chaque élément.
- df['A'].str.replace('^[1-9]', 'Z') : renvoie une série où le pattern est remplacé par la chaîne (si non présent, pas de remplacement. Utiliser regex = False si ce n'est pas un pattern mais une chaîne à remplacer.
- attention : df['A'].replace('abc', 'd') : remplace seulement les valeurs qui sont exactement abc par d, tandis que df['A'].str.replace('abc', 'd') remplace toutes les occurrences de abc par d ! Ce n'est pas la même fonction.
- s.str.extract('(\w+)(\d)', expand = True) : renvoie un dataframe avec une colonne par groupe de l'expression régulière. Si ça ne matche pas, met des NaN.
- Slicing d'une series : s = pandas.Series(['ACBDE', 'acbde']); s.str.slice(start = 1, stop = 3) donne la series ['CB', 'cb']
- si s = pandas.Series(['ab-cd', 'ef-gh', 'ij-kl']) et qu'on veut récupérer la series avec ce qu'il y a avant le tiret : s.str.split('-').str[0] donne la series ['ab', 'ef', 'ij']
Sélection de valeurs :
- s[s > 4] : une série contenant les valeurs supérieures à 4.
- s[s.notna()] : renvoie la série avec les valeurs nan éliminées.
- attention : quand on part d'une série avec indices numériques de 0 à n, et qu'on extrait une sous-série, les valeurs d'indices ne changent pas par rapport à leur valeur initiale (mais avec iat[] et iloc[], pas de problèmes).
Conversion d'une series :
- s.tolist() : conversion en liste.
- s.astype(str) : en string.
- s.astype(float) : en float.
Divers :
- s.to_frame() : convertit la série en DataFrame à une seule colonne (dont le nom est le nom de la série).
- s.to_frame(name = 'A') : on peut donner un nom à la colonne.
- s.memory_usage() : donne la mémoire utilisée en nombre d'octets.
Copyright python-simple.com
programmer en python, tutoriel python, graphes en python, Aymeric Duclert