Pandas Series에서 요소의 인덱스 찾기


154

나는 이것이 매우 기본적인 질문이라는 것을 알고 있지만 어떤 이유로 든 대답을 찾을 수 없습니다. 파이썬 팬더에서 시리즈의 특정 요소 색인을 어떻게 얻을 수 있습니까? (첫 번째로 충분할 것입니다)

즉, 나는 다음과 같은 것을 원합니다 :

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

확실히 루프를 사용하여 이러한 메소드를 정의 할 수 있습니다.

def find(s, el):
    for i in s.index:
        if s[i] == el: 
            return i
    return None

print find(myseries, 7)

그러나 더 좋은 방법이 있어야한다고 생각합니다. 있습니까?

답변:


199
>>> myseries[myseries == 7]
3    7
dtype: int64
>>> myseries[myseries == 7].index[0]
3

비록 더 나은 방법이 있어야한다고 인정하지만, 최소한 객체를 반복하고 반복하는 것을 피하고 C 레벨로 옮깁니다.


12
여기서 문제는 검색중인 요소가 실제로 목록에 있다고 가정한다는 것입니다. 범퍼 팬더는 찾기 작업이 내장되어 있지 않은 것 같습니다.
jxramos 2012 년

7
이 솔루션은 계열에 순차 정수 색인이있는 경우에만 작동합니다. 시리즈 색인이 날짜 / 시간 기준 인 경우 작동하지 않습니다.
앤드류 메 드린

43

인덱스로 변환하면 사용할 수 있습니다 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

중복 처리

In [5]: Index([1,1,2,2,3,4]).get_loc(2)
Out[5]: slice(2, 4, None)

연속하지 않은 경우 반환 부울 ​​배열을 반환합니다

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)

내부적으로 해시 테이블을 사용하므로 매우 빠릅니다.

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

Viktor가 지적했듯이 인덱스 생성에는 일회성 생성 오버 헤드가 있습니다 (예를 들어, 인덱스로 실제로 무언가를 할 때 발생합니다 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

1
@Jeff 만약 당신이 더 흥미로운 인덱스를 가지고 있다면 그렇게 쉬운 일이 아닙니다 ... 그러나 당신이 할 수있을 것 같아요s.index[_]
Andy Hayden

11
In [92]: (myseries==7).argmax()
Out[92]: 3

7이 미리 있다는 것을 알고 있다면 작동합니다. (myseries == 7) .any ()로 이것을 확인할 수 있습니다.

여러 개의 7을 설명하는 (또는 첫 번째 답변과 매우 유사한) 다른 접근 방식은

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']

7을 아는 것에 대한 요점은 미리 요소입니다. 그러나 any이중 반복이 필요하므로 검사를 사용하는 것은 이상적이지 않습니다. 여기에서 False볼 수있는 모든 조건을 공개 할 수 있는 멋진 사후 점검이 있습니다 .
jxramos

1
이 조건과 일치하는 요소가 없으면주의하여 오류가 argmax아닌 0을 반환합니다.
cs95

8

나는 여기에 모든 대답에 깊은 인상을 받았습니다. 이것은 새로운 해답이 아니며 모든 방법의 타이밍을 요약하려는 시도 일뿐입니다. 25 개의 요소가있는 시리즈의 경우를 고려하고 인덱스에 값이 포함될 수있는 일반적인 경우를 가정하고 시리즈의 끝 부분에있는 검색 값에 해당하는 인덱스 값을 원합니다.

다음은 Pandas 버전 0.25.3이 포함 된 Python 3.7의 2013 MacBook Pro에 대한 속도 테스트입니다.

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의 답변은 중복을 처리하지 않지만 가장 빠른 것 같습니다.

수정 : 죄송합니다. 목록 색인 방법을 사용하는 @Alex Spangher의 솔루션이 훨씬 빠릅니다.

최신 정보 : @EliadL의 답변이 추가되었습니다.

도움이 되었기를 바랍니다.

이러한 간단한 작업에는 복잡한 솔루션이 필요하고 많은 사람들이 너무 느립니다. 어떤 경우에는 일련의 25에서 값을 찾기 위해 0.5 밀리 초 이상.


1
감사. 그러나 한 번만 생성 하면되므로 측정 후에 myindex 는 안됩니까?
EliadL

당신은 그것을 주장 할 수 있지만, 이와 같은 조회가 얼마나 필요한지에 달려 있습니다. myindex조회를 여러 번 수행하려는 경우 에만 시리즈를 작성하는 것이 좋습니다. 이 테스트에서는 한 번만 필요했고 총 실행 시간이 중요하다고 가정했습니다.
Bill

1
오늘 밤 이것에 대한 필요성에 부딪 히고 여러 조회에서 동일한 Index 객체에서 .get_lock ()을 사용하는 것이 가장 빠를 것 같습니다. 대답의 개선은 인덱스 생성을 포함한 타이밍과 인덱스 생성 후 조회의 다른 타이밍을 모두 제공하는 것입니다.
Rick은

예, 좋은 지적입니다. @EliadL도 말했다. 일련의 정적 응용 프로그램 수에 따라 다릅니다. 계열의 값이 변경되면을 다시 작성해야합니다 pd.Index(myseries). 다른 방법에 공평하기 위해 나는 마지막 시리즈 이후 원래 시리즈가 변경되었다고 가정했습니다.

5

똑같이 불만족 스럽지만이를 수행하는 다른 방법은 다음과 같습니다.

s = pd.Series([1,3,0,7,5],index=[0,1,2,3,4])

list(s).index(7)

반환 : 3

현재 작업중 인 데이터 세트를 사용하여 정시에 테스트합니다 (임의로 간주).

[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

4

numpy를 사용하면 값을 찾은 다양한 배열을 얻을 수 있습니다.

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)

이것은 indecies의 배열을 포함하는 하나의 요소 튜플을 반환합니다. 여기서 7은 myseries의 값입니다.

(array([3], dtype=int64),)

3

Series.idxmax ()를 사용할 수 있습니다

>>> import pandas as pd
>>> myseries = pd.Series([1,4,0,7,5], index=[0,1,2,3,4])
>>> myseries.idxmax()
3
>>> 

5
이것은 max 요소가있는 색인 만 반환하는 것으로 보이며 index of certain element질문과 같은 특정 내용 은 아닙니다 .
jxramos

1

아직 언급되지 않은 또 다른 방법은 tolist 방법입니다.

myseries.tolist().index(7)

값이 Series에 존재한다고 가정하면 올바른 인덱스를 반환해야합니다.


1
@Alex Spangher는 '14. 그의 대답을보십시오. 테스트 결과에 두 버전을 모두 추가했습니다.
Bill

0

종종 여러 지수에서 가치가 발생합니다.

>>> 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')

0

이것은 내가 찾을 수있는 가장 기본적이고 확장 가능한 접근법입니다.

>>> myindex = pd.Series(myseries.index, index=myseries)

>>> myindex[7]
3

>>> myindex[[7, 5, 7]]
7    3
5    4
7    3
dtype: int64
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.