DataFrame Index에 기능 적용


84

Pandas의 인덱스에 함수를 적용하는 가장 좋은 방법은 무엇입니까 DataFrame? 현재 저는이 장황한 접근 방식을 사용하고 있습니다.

pd.DataFrame({"Month": df.reset_index().Date.apply(foo)})

어디 Date 인덱스의 이름이고 foo내가 적용하고있는 함수의 이름입니다.


6
않는 df.index.map(foo)일을?
— HYRY

1
"작동"하지만 Pandas Series가 아닌 numpy 배열을 반환합니다.
— Alex Rothberg 2013

1
당신의 최종 목표는 무엇입니까? DataFrame 생성자에 배열을 전달할 수 있습니다. 또는 같은 것을 할pd.Series(df.index).apply(foo)
— 로마 Pekar

그것은 완전히 기능이 ... 무엇을 따라
— 앤디 헤이든에게

1
기존 DataFrame의 인덱스 만 수정하려는 경우 @HYRY에서 다음을 수행 할 수 있습니다.df.index = df.index.map(foo)
— Ben

답변:


99

HYRY 가 의견에서 이미 제안 했듯이 Series.map 은 여기로 이동하는 방법입니다. 결과 시리즈에 인덱스를 설정하기 만하면됩니다.

간단한 예 :

df = pd.DataFrame({'d': [1, 2, 3]}, index=['FOO', 'BAR', 'BAZ'])
df
        d
FOO     1
BAR     2
BAZ     3

df.index = df.index.map(str.lower)
df
        d
foo     1
bar     2
baz     3

색인! = 시리즈

@OP가 지적한 바와 같습니다. df.index.map(str.lower)호출은 NumPy와 배열을 반환합니다. 이는 데이터 프레임 인덱스 가 시리즈가 아닌 numpy 배열을 기반으로 하기 때문 입니다.

인덱스를 Series로 만드는 유일한 방법은 그것에서 Series를 만드는 것입니다.

pd.Series(df.index.map(str.lower))

경고

Index클래스는 이제 서브 클래스 StringAccessorMixin는 다음과 같이 위의 작업을 할 수있는 수단,

df.index.str.lower()

이것은 여전히 ​​Series가 아닌 Index 객체를 생성합니다.


1
다중 인덱스를 사용하면 함수에서 두 항목을 모두 사용하려는 경우 슬라이싱을 사용할 수 있습니다 (예 : x[0]및 x[1].
— Elliott 2016

3
좀 더 짧은 방법df.index.map(str.lower)
— Zero

1
@JohnGalt 지적 해 주셔서 감사합니다. str.lower는 컴파일 된 cython 함수이고 내가 작성한 람다 함수는 그렇지 않기 때문에 더 짧을뿐만 아니라 더 빠릅니다.
— firelynx

12

인덱스에 "foo"함수를 적용하여 현재 DataFrame에서 열을 만들고 싶다고 가정합니다. 당신은 쓸 수 있습니다 ...

df['Month'] = df.index.map(foo)

시리즈 만 생성하려면 대신 할 수 있습니다.

pd.Series({x: foo(x) for x in foo.index})

1
pandas / numpy 에코 시스템에서 for 루프를 사용하는 것은 매우 권장되지 않습니다. 메모리가 매우 비효율적이며 더 큰 데이터 세트와 쉽게 충돌합니다.
— firelynx

3

많은 답변이 인덱스를 배열로 반환하므로 인덱스 이름 등에 대한 정보가 손실됩니다 (할 수는 있지만 pd.Series(index.map(myfunc), name=index.name)). MultiIndex에서도 작동하지 않습니다.

이 작업을 수행 한 방법은 "이름 바꾸기"를 사용하는 것입니다.

mix = pd.MultiIndex.from_tuples([[1, 'hi'], [2, 'there'], [3, 'dude']], names=['num', 'name'])
data = np.random.randn(3)
df = pd.Series(data, index=mix)
print(df)
num  name 
1    hi       1.249914
2    there   -0.414358
3    dude     0.987852
dtype: float64

# Define a few dictionaries to denote the mapping
rename_dict = {i: i*100 for i in df.index.get_level_values('num')}
rename_dict.update({i: i+'_yeah!' for i in df.index.get_level_values('name')})
df = df.rename(index=rename_dict)
print(df)
num  name       
100  hi_yeah!       1.249914
200  there_yeah!   -0.414358
300  dude_yeah!     0.987852
dtype: float64

이것에 대한 유일한 트릭은 당신의 인덱스가 다른 다중 인덱스 레벨과 함께 고유 한 레이블을 가져야한다는 것입니다.하지만 아마도 저보다 더 똑똑한 누군가가 그것을 극복하는 방법을 알고있을 것입니다. 내 목적을 위해 이것은 95 %의 시간 동안 작동합니다.


3

언제든지 해당 to_series()방법을 사용하여 색인을 변환 한 다음 선호 사항 / 필요에 따라 apply또는을 변환 할 수 있습니다 map.

ret = df.index.map(foo)                # Returns pd.Index
ret = df.index.to_series().map(foo)    # Returns pd.Series
ret = df.index.to_series().apply(foo)  # Returns pd.Series

위의 모든 항목은의 신규 또는 기존 열에 직접 할당 할 수 있습니다 df.

df["column"] = ret

완전성을 위해 : pd.Index.map, pd.Series.map그리고 pd.Series.apply모두 요소별로 작동합니다. 나는 종종 또는로 map표시되는 조회를 적용 하는 데 사용 합니다 . 추가와 함께 어떤 기능을 전달할 수 있기 때문에 더 일반적이기 거나 . 차이점 및 상기에서 설명 이 SO 실 . 왜 생략 되었는지 모르겠습니다 .dictspd.Seriesapplyargskwargsapplymappd.Index.apply

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.