여러 열을 참조하는 팬더 '적용'기능이 작동하지 않는 이유는 무엇입니까? [닫은]


239

다음 데이터 프레임에서 여러 열을 사용할 때 Pandas apply 함수에 문제가 있습니다.

df = DataFrame ({'a' : np.random.randn(6),
                 'b' : ['foo', 'bar'] * 3,
                 'c' : np.random.randn(6)})

다음 기능

def my_test(a, b):
    return a % b

이 기능을 다음과 같이 적용하려고하면 :

df['Value'] = df.apply(lambda row: my_test(row[a], row[c]), axis=1)

오류 메시지가 나타납니다.

NameError: ("global name 'a' is not defined", u'occurred at index 0')

이 메시지를 이해하지 못하고 이름을 올바르게 정의했습니다.

이 문제에 대한 도움을 주시면 감사하겠습니다.

최신 정보

당신의 도움을 주셔서 감사합니다. 실제로 코드에 구문 오류가 발생했습니다. 인덱스에 ''를 넣어야합니다. 그러나 여전히 다음과 같은보다 복잡한 기능을 사용하여 동일한 문제가 발생합니다.

def my_test(a):
    cum_diff = 0
    for ix in df.index():
        cum_diff = cum_diff + (a - df['a'][ix])
    return cum_diff 

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

이것은 데이터 프레임 열을 참조하는 구문 오류에 관한 것이며 함수에 인수가 필요한 이유는 무엇입니까? 두 번째 질문에 관해서는 함수 my_test(a)df인수로 전달되지 않은 이후로 무엇이 무엇인지 알지 못합니다 ( df전 세계적으로 끔찍한 연습이 아닌 경우 ). 함수 내에서 필요한 모든 값을 인수 (바람직하게는 순서대로)로 전달해야합니다. 그렇지 않으면 함수가 어디서 df오는지 어떻게 알 수 있습니까? 또한 전역 변수로 가득 찬 네임 스페이스에서 프로그래밍하는 것은 좋지 않습니다. 이러한 오류는 잡을 수 없습니다.
smci

답변:


379

''문자열 을 잊어 버린 것 같습니다 .

In [43]: df['Value'] = df.apply(lambda row: my_test(row['a'], row['c']), axis=1)

In [44]: df
Out[44]:
                    a    b         c     Value
          0 -1.674308  foo  0.343801  0.044698
          1 -2.163236  bar -2.046438 -0.116798
          2 -0.199115  foo -0.458050 -0.199115
          3  0.918646  bar -0.007185 -0.001006
          4  1.336830  foo  0.534292  0.268245
          5  0.976844  bar -0.773630 -0.570417

BTW, 제 생각에는 다음과 같은 방식이 더 우아합니다.

In [53]: def my_test2(row):
....:     return row['a'] % row['c']
....:     

In [54]: df['Value'] = df.apply(my_test2, axis=1)

고마워요, 당신은 '' 그러나 여전히 더 복잡한 기능과 동일한 문제가 있습니다. 도와 주셔서 감사합니다. 감사합니다
Andy

5
@Andy [53-54]에 따르면 더 복잡한 기능을 적용 할 수 있습니다.
Andy Hayden

@Andy는 In [53] 방식과 같은 복잡한 기능을 정의 할 수 있습니다.
기다리는 쿠오

모든 적용 전략이 동일하게 수행됩니까? 나는 팬더를 처음 사용하고 항상 약간 수수께끼를 적용한다는 것을 알았지 만 [53-54]의 전략은 이해하기 쉽고 기억하기 쉽습니다 ... 큰 테이블에서 다른 형태의 적용만큼 빠릅니다. 제시?
whytheq

작은 방법이라도 별도의 방법을 만드는 것이 더 우아하다고 생각되는 이유는 무엇입니까? 나는 7 년 동안 파이썬에서 중요한 프로젝트를 해왔지만 pythonista이것을 포함하여 일부 관점으로 인해 고려되지는 않을 것 입니다.
javadba

33

계산 (열 a) % (열 b)를 계산하려면 필요하지 않습니다 apply. 직접 수행하십시오.

In [7]: df['a'] % df['c']                                                                                                                                                        
Out[7]: 
0   -1.132022                                                                                                                                                                    
1   -0.939493                                                                                                                                                                    
2    0.201931                                                                                                                                                                    
3    0.511374                                                                                                                                                                    
4   -0.694647                                                                                                                                                                    
5   -0.023486                                                                                                                                                                    
Name: a

16
나는 여러 열에 함수를 적용 할 때 내 문제를 보여주는 예일 뿐이다.
Andy

18

DataFrame df의 열 'a'와 'b'에 add5 함수를 적용한다고 가정 해 봅시다.

def add5(x):
    return x+5

df[['a', 'b']].apply(add5)

코드 스 니펫을 시도하는 동안 다음 오류가 발생합니다. TypeError : ( 'b이어야하며 int가 아니어야합니다.', '색인 b에서 발생했습니다') 그 점을 살펴보십시오.
debaonline4u

데이터 프레임의 열 b는 문자열 유형 또는 객체 유형 열이며 숫자와 함께 추가 할 정수 열이어야합니다.
Mir_Murtaza

할당 후에 만 ​​변경 사항이 적용되지 않습니까?
S.aad

11

위의 모든 제안은 효과가 있지만 계산을보다 효율적으로하려면 numpy vector 연산을 사용해야합니다 (여기에서 지적한 바와 같이) .

import pandas as pd
import numpy as np


df = pd.DataFrame ({'a' : np.random.randn(6),
             'b' : ['foo', 'bar'] * 3,
             'c' : np.random.randn(6)})

예제 1 : 다음으로 반복 pandas.apply():

%%timeit
def my_test2(row):
    return row['a'] % row['c']

df['Value'] = df.apply(my_test2, axis=1)

가장 느린 실행은 가장 빠른 실행보다 7.49 배 길었습니다. 이는 중간 결과가 캐시되고 있음을 의미 할 수 있습니다. 1000 루프, 루프 당 최고 3 : 481 µs

예제 2 : 다음을 사용하여 벡터화 pandas.apply():

%%timeit
df['a'] % df['c']

가장 느린 실행은 가장 빠른 실행보다 458.85 배 길었습니다. 이는 중간 결과가 캐시되고 있음을 의미 할 수 있습니다. 10000 루프, 루프 당 최고 3 : 70.9 µs

예제 3 : numpy 배열을 사용하여 벡터화 :

%%timeit
df['a'].values % df['c'].values

가장 느린 실행은 가장 빠른 실행보다 7.98 배 길었습니다. 이는 중간 결과가 캐시되고 있음을 의미 할 수 있습니다. 100000 루프, 루프 당 최고 3 : 6.39 µs

따라서 numpy 배열을 사용하여 벡터화하면 속도가 거의 2 배 향상되었습니다.


예를 들어 6을 10K로 바꾸면 각각 248ms, 332µs, 263µs가됩니다. 따라서 두 벡터화 된 솔루션은 서로 훨씬 더 가깝지만 벡터화되지 않은 솔루션은 1000 배 느립니다. (python-3.7에서 테스트)
stason

3

이것은 이전 솔루션과 동일하지만 df.apply 자체에서 함수를 정의했습니다.

df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1)

2

위에서 설명한 세 가지를 모두 비교했습니다.

값 사용

% timeit df [ 'value'] = df [ 'a']. values ​​% df [ 'c']. values

루프 당 139 µs ± 1.91 µs (평균 런 7 회 실행, 각 10000 루프)

값이없는

% timeit df [ 'value'] = df [ 'a'] % df [ 'c'] 

루프 당 216 µs ± 1.86 µs (평균 런 7 회 실행, 각 1000 루프)

기능 적용

% timeit df [ 'Value'] = df.apply (lambda row : row [ 'a'] % row [ 'c'], axis = 1)

루프 당 474 µs ± 5.07 µs (평균 7 번의 런, 평균 1000 루프)

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