Znajdź indeks elementu w serii pandy
Wiem, że to bardzo podstawowe pytanie, ale z jakiegoś powodu nie mogę znaleźć odpowiedzi. Jak Mogę uzyskać indeks pewnego elementu serii w Pythonie? (pierwsze wystąpienie wystarczy)
Tzn. chciałbym coś takiego:
import pandas as pd
myseries = pd.Series([1,4,0,7,5], index=[0,1,2,3,4])
print myseries.find(7) # should output 3
Oczywiście, możliwe jest zdefiniowanie takiej metody za pomocą pętli:
def find(s, el):
for i in s.index:
if s[i] == el:
return i
return None
print find(myseries, 7)
Ale zakładam, że powinien być lepszy sposób. Naprawdę? 10 answers
>>> myseries[myseries == 7]
3 7
dtype: int64
>>> myseries[myseries == 7].index[0]
3
Choć przyznaję, że powinien być lepszy sposób, aby to zrobić, ale to przynajmniej unika iteracji i pętli przez obiekt i przenosi go na poziom C.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-07 14:03:06
Konwersja do indeksu, możesz użyć get_loc
In [1]: myseries = pd.Series([1,4,0,7,5], index=[0,1,2,3,4])
In [3]: Index(myseries).get_loc(7)
Out[3]: 3
In [4]: Index(myseries).get_loc(10)
KeyError: 10
Obsługa duplikatów
In [5]: Index([1,1,2,2,3,4]).get_loc(2)
Out[5]: slice(2, 4, None)
Zwróci tablicę logiczną, jeśli nieciągłe zwróci
In [6]: Index([1,1,2,1,3,2,4]).get_loc(2)
Out[6]: array([False, False, True, False, False, True, False], dtype=bool)
Używa hashtable wewnętrznie, tak szybko
In [7]: s = Series(randint(0,10,10000))
In [9]: %timeit s[s == 5]
1000 loops, best of 3: 203 µs per loop
In [12]: i = Index(s)
In [13]: %timeit i.get_loc(5)
1000 loops, best of 3: 226 µs per loop
Jak wskazuje Viktor, istnieje Jednorazowa możliwość utworzenia indeksu (jego powstanie, gdy rzeczywiście coś z nim zrobisz, np. is_unique
)
In [2]: s = Series(randint(0,10,10000))
In [3]: %timeit Index(s)
100000 loops, best of 3: 9.6 µs per loop
In [4]: %timeit Index(s).is_unique
10000 loops, best of 3: 140 µs per loop
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-20 12:19:16
In [92]: (myseries==7).argmax()
Out[92]: 3
To działa, jeśli wiesz, że 7 jest tam z góry. Możesz to sprawdzić za pomocą (myseries = = 7).any ()
Innym podejściem (bardzo podobnym do pierwszej odpowiedzi), które również odpowiada wielokrotności 7 (lub żadnej) jest
In [122]: myseries = pd.Series([1,7,0,7,5], index=['a','b','c','d','e'])
In [123]: list(myseries[myseries==7].index)
Out[123]: ['b', 'd']
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 08:51:51
Jestem pod wrażeniem wszystkich odpowiedzi tutaj. To nie jest nowa odpowiedź, tylko próba podsumowania czasów wszystkich tych metod. Rozważałem przypadek serii z 25 elementami i założyłem ogólny przypadek, w którym indeks może zawierać dowolne wartości i chcesz wartość indeksu odpowiadającą wartości wyszukiwania, która jest pod koniec serii.
Oto testy prędkości Na 2013 MacBook Pro w Pythonie 3.7 z Pandas w wersji 0.25.3.
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: data = [406400, 203200, 101600, 76100, 50800, 25400, 19050, 12700,
...: 9500, 6700, 4750, 3350, 2360, 1700, 1180, 850,
...: 600, 425, 300, 212, 150, 106, 75, 53,
...: 38]
In [4]: myseries = pd.Series(data, index=range(1,26))
In [5]: myseries[21]
Out[5]: 150
In [7]: %timeit myseries[myseries == 150].index[0]
416 µs ± 5.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [8]: %timeit myseries[myseries == 150].first_valid_index()
585 µs ± 32.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [9]: %timeit myseries.where(myseries == 150).first_valid_index()
652 µs ± 23.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [10]: %timeit myseries.index[np.where(myseries == 150)[0][0]]
195 µs ± 1.18 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [11]: %timeit pd.Series(myseries.index, index=myseries)[150]
178 µs ± 9.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [12]: %timeit myseries.index[pd.Index(myseries).get_loc(150)]
77.4 µs ± 1.41 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [13]: %timeit myseries.index[list(myseries).index(150)]
12.7 µs ± 42.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [14]: %timeit myseries.index[myseries.tolist().index(150)]
9.46 µs ± 19.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
@Jeff ' s answer wydaje się być najszybszy-chociaż nie obsługuje duplikatów.
korekta: Sorry, przegapiłem jedno, @Alex Spangher rozwiązanie przy użyciu metody indeksu listy jest zdecydowanie najszybsze.
Aktualizacja: dodał (a) odpowiedź @EliadL.
Mam nadzieję, że to pomoże. Niesamowite, że tak prosta operacja wymaga tak skomplikowanych rozwiązań, a wiele z nich jest tak powolnych. Ponad pół milisekundy w niektórych przypadkach, aby znaleźć wartość w serii 25.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-01 19:46:25
Innym sposobem, aby to zrobić, choć równie niesatysfakcjonujące jest:
s = pd.Series([1,3,0,7,5],index=[0,1,2,3,4])
list(s).index(7)
Zwraca: 3
Na testach czasowych przy użyciu bieżącego zestawu danych, z którym pracuję (Uznaj to za przypadkowe):
[64]: %timeit pd.Index(article_reference_df.asset_id).get_loc('100000003003614')
10000 loops, best of 3: 60.1 µs per loop
In [66]: %timeit article_reference_df.asset_id[article_reference_df.asset_id == '100000003003614'].index[0]
1000 loops, best of 3: 255 µs per loop
In [65]: %timeit list(article_reference_df.asset_id).index('100000003003614')
100000 loops, best of 3: 14.5 µs per loop
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-17 20:09:24
Jeśli używasz numpy, możesz uzyskać tablicę indecies, że twoja wartość została znaleziona:
import numpy as np
import pandas as pd
myseries = pd.Series([1,4,0,7,5], index=[0,1,2,3,4])
np.where(myseries == 7)
Zwraca krotkę jednego elementu zawierającą tablicę indecies, gdzie 7 jest wartością w myseries:
(array([3], dtype=int64),)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-05 00:01:51
Możesz używać serii.idxmax ()
>>> import pandas as pd
>>> myseries = pd.Series([1,4,0,7,5], index=[0,1,2,3,4])
>>> myseries.idxmax()
3
>>>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-25 05:15:59
Innym sposobem, który nie został jeszcze wymieniony, jest metoda tolist:
myseries.tolist().index(7)
Powinien zwrócić poprawny indeks, zakładając, że wartość istnieje w szeregu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-29 22:02:43
Jest to najbardziej natywne i skalowalne podejście, jakie mogłem znaleźć:
>>> myindex = pd.Series(myseries.index, index=myseries)
>>> myindex[7]
3
>>> myindex[[7, 5, 7]]
7 3
5 4
7 3
dtype: int64
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-02 11:17:12
Często twoja wartość występuje przy wielu indeksach:
>>> myseries = pd.Series([0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1])
>>> myseries.index[myseries == 1]
Int64Index([3, 4, 5, 6, 10, 11], dtype='int64')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-21 09:49:15