Je découpe une trame de données pandas et il semble que j'obtienne des tranches inattendues en utilisant .loc, au moins par rapport à la découpe numpy et ordinaire en python. Voir l'exemple ci-dessous.

>>> import pandas as pd
>>> a = pd.DataFrame([[0,1,2],[3,4,5],[4,5,6],[9,10,11],[34,2,1]])
>>> a
    0   1   2
0   0   1   2
1   3   4   5
2   4   5   6
3   9  10  11
4  34   2   1
>>> a.loc[1:3, :]
   0   1   2
1  3   4   5
2  4   5   6
3  9  10  11
>>> a.values[1:3, :]
array([[3, 4, 5],
       [4, 5, 6]])

Fait intéressant, cela ne se produit qu'avec .loc, pas avec .iloc.

>>> a.iloc[1:3, :]
   0  1  2
1  3  4  5
2  4  5  6

Ainsi, .loc semble inclure l'index de terminaison, mais numpy et .iloc ne le sont pas.

D'après les commentaires, il semble que ce ne soit pas un bug et nous sommes bien prévenus. Mais pourquoi est-ce le cas?

2
jtorca 15 mars 2019 à 20:05

2 réponses

Meilleure réponse

N'oubliez pas que .loc est principalement une indexation basée sur les étiquettes. La décision d'inclure le point de terminaison d'arrêt devient beaucoup plus évidente lorsque vous travaillez avec un non-RangeIndex:

df = pd.DataFrame([1,2,3,4], index=list('achz'))
#   0
#a  1
#c  2
#h  3
#z  4

Si je souhaite sélectionner toutes les lignes entre 'a' et 'h' (inclus), je ne connais que 'a' et 'h'. Afin d'être cohérent avec les autres découpages en python, vous devez également savoir quel index suit 'h', qui dans ce cas est 'z' mais aurait pu être n'importe quoi.


Il y a aussi une section des documents cachée qui explique ce choix de conception Les points de terminaison sont inclusifs

6
ALollz 8 août 2019 à 20:39

En plus du point dans les docs, l'indexation de tranche pandas à l'aide de .loc n'est pas basée sur l'index de cellule. Il s'agit en fait d'une indexation basée sur des valeurs (dans la documentation sur les pandas, cela s'appelle "basé sur des étiquettes", mais pour les données numériques je préfère le terme "basé sur des valeurs"), alors qu'avec .iloc c'est indexation traditionnelle des cellules de style numpy.

De plus, l'indexation basée sur les valeurs est inclusive à droite, alors que l'indexation des cellules ne l'est pas. Essayez simplement ce qui suit :

a = pd.DataFrame([[0,1,2],[3,4,5],[4,5,6],[9,10,11],[34,2,1]])
a.index = [0, 1, 2, 3.1, 4]  # add a float index

# value based slicing: the following will output all value up to the slice value
a.loc[1:3.1]
# Out:
# 0    1   2
# 1.0  3   4   5
# 2.0  4   5   6
# 3.1  9  10  11

# index based slicing: will raise an error, since only integers are allowed
a.iloc[1:3.1]
# Out: TypeError: cannot do slice indexing on <class 'pandas.core.indexes.numeric.Float64Index'> with these indexers [3.2] of <class 'float'>

Pour donner une réponse explicite à votre question pourquoi il est inclusif :
Lors de l'utilisation de valeurs/étiquettes comme indices, il est, du moins à mon avis, intuitif, que le dernier indice soit inclus. Pour autant que je sache, il s'agit d'une décision de conception sur la façon dont la fonction implémentée est censée fonctionner.

3
Scotty1- 15 mars 2019 à 17:30