Je souhaite attribuer à chaque ligne d'un dataframe un intervalle, de sorte que toutes les lignes ne se chevauchent pas et couvrent toute la plage possible. En conséquence, je peux filtrer les lignes en fonction des valeurs comprises dans un intervalle donné.
J'ai utilisé pd.Interval , mais lorsque j'ai essayé le filtrage `` normal '', cela n'a pas fonctionné:
rating stars 1 average [2, 4)
Cela a donné l'erreur suivante:
KeyError Traceback (most recent call last) /usr/local/lib/python3.6/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance) 2656 try: -> 2657 return self._engine.get_loc(key) 2658 except KeyError: pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc() pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc() pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item() pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item() KeyError: False
Un code de travail devrait donner le résultat:
df = pd.DataFrame({"rating":["bad","average","good"],
"stars":[pd.Interval(left=0,right=2,closed="left"),
pd.Interval(left=2,right=4,closed="left"),
pd.Interval(left=4,right=5,closed="both")]})
stars_val=2.5
filtered_df = df[stars_val in df.stars]
3 Réponses :
Vous pouvez l'utiliser:
[False, True, False]
Résultat:
filtered
Explication: p>
False
Résultat:
stars_val in df.stars
gardez à l'esprit que vous avez besoin d'une liste de booléens pour filtrer df, après avoir exécuté mon code, vous obtiendrez:
rating stars 1 average [2, 4)
Sortie:
filtered=[]
for i in df.index:
filtered.append(stars_val in df.stars[i])
filtered_df=df[filtered]
à cause de ce df [filtré] fonctionne, car la longueur de la liste correspond à la longueur de la colonne de votre dataframe
Merci pour l'explication détaillée. J'ai préféré @ALollz réponse , car c'est un one-liner qui peut être utilisé plus facilement avec d'autres opérateurs pour un filtrage supplémentaire.
df.stars est une série. Vous voulez vérifier si stars_val est dans chaque intervalle de la série
filtered_df = df[[stars_val in x for x in df.stars]]
rating stars
1 average [2, 4)
Si tous vos intervalles ont le même fermé , votre colonne sera soutenue par un IntervalArray et vous pouvez utiliser IntervalArray.contains méthode pour une implémentation vectorisée:
In [2]: np.random.seed(123)
In [3]: start = np.random.randint(100, size=1000)
In [4]: ia = pd.arrays.IntervalArray.from_arrays(start, start + 5)
In [5]: df = pd.DataFrame({'A': list('abcde') * 200, 'B': ia})
In [6]: df.head()
Out[6]:
A B
0 a (66, 71]
1 b (92, 97]
2 c (98, 103]
3 d (17, 22]
4 e (83, 88]
In [7]: df[df['B'].array.contains(70)]
Out[7]:
A B
0 a (66, 71]
20 a (68, 73]
23 d (67, 72]
27 c (66, 71]
45 a (69, 74]
87 c (67, 72]
111 b (65, 70]
128 d (68, 73]
133 d (65, 70]
135 a (67, 72]
155 a (65, 70]
177 c (69, 74]
193 d (67, 72]
217 c (69, 74]
221 b (66, 71]
223 d (69, 74]
227 c (66, 71]
243 d (66, 71]
250 a (67, 72]
251 b (65, 70]
263 d (68, 73]
407 c (65, 70]
419 e (69, 74]
425 a (65, 70]
446 b (69, 74]
449 e (69, 74]
451 b (66, 71]
523 d (66, 71]
552 c (68, 73]
589 e (66, 71]
609 e (69, 74]
613 d (68, 73]
627 c (69, 74]
637 c (68, 73]
650 a (67, 72]
674 e (69, 74]
711 b (69, 74]
769 e (67, 72]
777 c (69, 74]
800 a (66, 71]
803 d (68, 73]
818 d (69, 74]
822 c (67, 72]
883 d (66, 71]
889 e (68, 73]
944 e (67, 72]
953 d (69, 74]
966 b (65, 70]
Des intervalles fermés mixtes donnent un tableau object , vous devrez donc utiliser une implémentation moins efficace comme ce que @ALollz a suggéré. p>