Supposons un dataframe facile, par exemple
A B
0 1 0.810743
1 2 0.595866
2 3 0.154888
3 4 0.472721
4 5 0.894525
5 6 0.978174
6 7 0.859449
7 8 0.541247
8 9 0.232302
9 10 0.276566
Comment puis-je récupérer une valeur d'index d'une ligne, étant donné une condition? Par exemple: dfb = df[df['A']==5].index.values.astype(int)
renvoie [4]
, mais ce que j'aimerais obtenir, c'est simplement 4
. Cela me cause des ennuis plus tard dans le code.
En fonction de certaines conditions, je souhaite disposer d’un enregistrement des index pour lesquels cette condition est remplie, puis sélectionner des lignes entre elles.
J'ai essayé
dfb = df[df['A']==5].index.values.astype(int)
dfbb = df[df['A']==8].index.values.astype(int)
df.loc[dfb:dfbb,'B']
pour une sortie désirée
A B
4 5 0.894525
5 6 0.978174
6 7 0.859449
mais je reçois TypeError: '[4]' is an invalid key
Le plus simple est add _[0]
_ - sélectionnez la première valeur de la liste avec un élément:
_dfb = df[df['A']==5].index.values.astype(int)[0]
dfbb = df[df['A']==8].index.values.astype(int)[0]
_
_dfb = int(df[df['A']==5].index[0])
dfbb = int(df[df['A']==8].index[0])
_
Mais si possible, certaines valeurs ne correspondent pas, une erreur est générée, car la première valeur n'existe pas.
La solution est d'utiliser next
avec iter
pour obtenir le paramètre par défaut si les valeurs ne correspondent pas:
_dfb = next(iter(df[df['A']==5].index), 'no match')
print (dfb)
4
dfb = next(iter(df[df['A']==50].index), 'no match')
print (dfb)
no match
_
Il semble alors nécessaire de soustraire _1
_:
_print (df.loc[dfb:dfbb-1,'B'])
4 0.894525
5 0.978174
6 0.859449
Name: B, dtype: float64
_
Une autre solution avec boolean indexing
ou query
:
_print (df[(df['A'] >= 5) & (df['A'] < 8)])
A B
4 5 0.894525
5 6 0.978174
6 7 0.859449
print (df.loc[(df['A'] >= 5) & (df['A'] < 8), 'B'])
4 0.894525
5 0.978174
6 0.859449
Name: B, dtype: float64
_
_print (df.query('A >= 5 and A < 8'))
A B
4 5 0.894525
5 6 0.978174
6 7 0.859449
_
Pour répondre à la question initiale sur l'obtention de l'index sous forme d'entier pour la sélection souhaitée, voici ce qui fonctionne:
df[df['A']==5].index.item()
La nature de vouloir inclure la ligne où A == 5
et toutes les lignes jusqu'à mais pas , y compris la ligne où A == 8
signifie que nous allons finissez par utiliser iloc
(loc
inclut les deux extrémités de la tranche).
Afin d'obtenir les étiquettes d'index, nous utilisons idxmax
. Cela retournera la première position de la valeur maximale. Je lance ceci sur une série booléenne où A == 5
(puis lorsque A == 8
) qui renvoie la valeur d'index de lorsque A == 5
se produit pour la première fois (même chose pour A == 8
).
Ensuite, j'utilise searchsorted
pour trouver la position ordinale de l'emplacement de l'étiquette d'index (que j'ai trouvée ci-dessus). C'est ce que j'utilise dans iloc
.
i5, i8 = df.index.searchsorted([df.A.eq(5).idxmax(), df.A.eq(8).idxmax()])
df.iloc[i5:i8]
numpy
vous pouvez encore améliorer cela en utilisant les objets numpy sous-jacents, les fonctions analogues de numpy. Je l'ai enveloppé dans une fonction pratique.
def find_between(df, col, v1, v2):
vals = df[col].values
mx1, mx2 = (vals == v1).argmax(), (vals == v2).argmax()
idx = df.index.values
i1, i2 = idx.searchsorted([mx1, mx2])
return df.iloc[i1:i2]
find_between(df, 'A', 5, 8)