팬더 : 단일 열에 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.