팬더 : 단일 열에 apply () 함수를 어떻게 사용할 수 있습니까?


255

두 개의 열이있는 팬더 데이터 프레임이 있습니다. 두 번째 열에 영향을주지 않고 첫 번째 열의 값을 변경하고 첫 번째 열 값만 변경하여 전체 데이터 프레임을 다시 가져와야합니다. 팬더에서 apply를 사용하여 어떻게 할 수 있습니까?


4
입력 샘플 데이터와 원하는 출력을 게시하십시오.
— Fabio Lamanna 2016 년

apply이런 상황에서는 거의 사용하지 마십시오 . 대신 컬럼에서 직접 조작하십시오.
— Ted Petrou

Ted Petrou가 말했듯이 apply가능한 한 많이 사용하지 마십시오 . 반드시 사용해야할지 확실하지 않으면 사용하지 않을 수 있습니다. 코드에서 pandas apply () 를 언제 사용하고 싶습니까? .
— cs95

질문은 완전히 명확하지 않습니다. 열의 모든 요소에 함수를 적용하거나 함수를 열에 전체적으로 적용합니까 (예 : 열 반전)?
— Pierre ALBARÈDE

답변:


336

샘플 데이터 프레임 df은 다음과 같습니다.

a,b
1,2
2,3
3,4
4,5

당신이 원하는 것은 :

df['a'] = df['a'].apply(lambda x: x + 1)

그 결과는 다음과 같습니다.

   a  b
0  2  2
1  3  3
2  4  4
3  5  5

9
apply이런 상황에서 절대로 사용해서는 안됩니다
— Ted Petrou

5
@TedPetrou 완벽하게 맞습니다. OP가 요청한 것처럼 하나의 단일 열에 일반 함수를 적용하는 방법에 대한 예제 일뿐입니다.
— Fabio Lamanna

14
이렇게하면 다음과 같은 경고 메시지가 나타납니다. "DataFrame에서 슬라이스 복사본에 값을 설정하려고합니다. 대신 .loc [row_indexer, col_indexer] = value를 사용하십시오"
— dagrun

24
호기심의 문제로 해당 상황에서 왜 적용하지 않아야합니까? 상황이 정확히 무엇입니까?
— 삼촌 벤 벤

19
@UncleBenBen은 일반적으로 apply벡터화 된 함수보다 훨씬 느린 내부 루프 오버 행을 사용합니다 df.a = df.a / 2( 예 : Mike Muller 답변 참조).
— Fabio Lamanna

66

다음과 같이 단일 컬럼을 사용하는 것이 좋습니다 map().

df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9



df['a'] = df['a'].map(lambda a: a / 2.)

      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

78
단일 컬럼 map()보다 나은 이유는 무엇 apply()입니까?
— ChaimG

2
이것은 매우 유용했습니다. 열에 저장된 경로에서 파일 이름을 추출하는 데 사용했습니다.df['file_name'] = df['Path'].map(lambda a: os.path.basename(a))
— mmann1123

46
map ()은 Series (예 : 단일 열) 용이며 한 번에 하나의 셀에서 작동하지만 apply ()는 DataFrame 용이며 한 번에 전체 행에서 작동합니다.
— jpcgt

3
@jpcgt 이것은이 경우에 적용하는 것보다지도가 더 빠르다는 것을 의미합니까?
— Viragos

@ChaimG 나는이 OS가 잘 설명 참조 : stackoverflow.com/a/19798528/571828
— 象 嘉 道

40

전혀 기능이 필요하지 않습니다. 전체 열에서 직접 작업 할 수 있습니다.

데이터 예 :

>>> df = pd.DataFrame({'a': [100, 1000], 'b': [200, 2000], 'c': [300, 3000]})
>>> df

      a     b     c
0   100   200   300
1  1000  2000  3000

열의 모든 값의 절반 a:

>>> df.a = df.a / 2
>>> df

     a     b     c
0   50   200   300
1  500  2000  3000

열의 모든 요소를 ​​"/"로 나누고 첫 번째 부분을 가져 오려면 어떻게해야합니까?
— K47

12

주어진 응답은 정확하지만 초기 데이터 프레임을 수정하는 것은 항상 바람직하지는 않습니다. OP가 "using apply" 을 예로 요청한 경우 새 데이터 프레임을 반환하는 버전을 원할 수도 있습니다 apply.

이것은 다음을 사용하여 가능합니다 assign: assign설명서에 나와있는 것처럼 기존 열에 유효합니다 (강조는 내 것입니다).

DataFrame에 새 열을 할당하십시오.

새 열 외에 모든 원래 열이 있는 새 개체 를 반환 합니다. 재 할당 된 기존 열을 덮어 씁니다 .

한마디로 :

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([{'a': 15, 'b': 15, 'c': 5}, {'a': 20, 'b': 10, 'c': 7}, {'a': 25, 'b': 30, 'c': 9}])

In [3]: df.assign(a=lambda df: df.a / 2)
Out[3]: 
      a   b  c
0   7.5  15  5
1  10.0  10  7
2  12.5  30  9

In [4]: df
Out[4]: 
    a   b  c
0  15  15  5
1  20  10  7
2  25  30  9

함수는 수정하려는 열뿐만 아니라 전체 데이터 프레임에 전달되므로 람다에서 올바른 열을 선택해야합니다.


9

apply 함수의 실행 속도에 정말로 관심이 있고 작업 할 거대한 데이터 세트가있는 경우 빠른 실행을 사용하여 더 빠르게 실행할 수 있습니다. 다음은 팬더 데이터 프레임에서 빠른 실행을위한 예입니다.

import pandas as pd
import swifter

def fnc(m):
    return m*3+4

df = pd.DataFrame({"m": [1,2,3,4,5,6], "c": [1,1,1,1,1,1], "x":[5,3,6,2,6,1]})

# apply a self created function to a single column in pandas
df["y"] = df.m.swifter.apply(fnc)

이렇게하면 모든 CPU 코어가 결과를 계산할 수 있으므로 일반 적용 기능보다 훨씬 빠릅니다. 그것이 당신에게 유용하게되면 알려주세요.


1

datetime을 사용하고 null 또는 빈 공간을 고려하여 복잡한 계산을 시도해 보겠습니다. 날짜 시간 열에서 30 년을 줄이고 apply방법을 사용 lambda하고 날짜 시간 형식을 변환하고 있습니다. 줄 if x != '' else x은 빈 공간이나 널을 모두 처리합니다.

df['Date'] = df['Date'].fillna('')
df['Date'] = df['Date'].apply(lambda x : ((datetime.datetime.strptime(str(x), '%m/%d/%Y') - datetime.timedelta(days=30*365)).strftime('%Y%m%d')) if x != '' else x)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.