2012-12-13 6 views
15

또 다른 팬더 질문입니다.팬더의 변환이 그룹 출력을 정렬 할 수 없습니다.

한다고 가정 나는 팁에 대한 몇 가지 정보를 가지고 데이터 분석 및 팬더에 대한 읽기 웨스 맥키 니의 훌륭한 책

, 나는 내가 일을해야한다고 생각 다음과 같은 일이 발생했습니다.

In [119]: 

tips.head() 
Out[119]: 
total_bill tip  sex  smoker day time size tip_pct 
0 16.99 1.01 Female False Sun  Dinner 2 0.059447 
1 10.34 1.66 Male False Sun  Dinner 3 0.160542 
2 21.01 3.50 Male False Sun  Dinner 3 0.166587 
3 23.68 3.31 Male False Sun  Dinner 2 0.139780 
4 24.59 3.61 Female False Sun  Dinner 4 0.146808 

와 나는 즉, 흡연자와 비 흡연자를위한 tip_pct 별도로, 전체 법안 관련 5 대 요령을 알고 싶어요. 나는이 같은 동일한 기능을 수행 할 변환 '팬더을 사용하고 싶었 다음

def top(df, n=5, column='tip_pct'): 
    return df.sort_index(by=column)[-n:] 

In [101]: 

tips.groupby('smoker').apply(top) 
Out[101]: 
      total_bill tip sex smoker day time size tip_pct 
smoker         
False 88 24.71 5.85 Male False Thur Lunch 2 0.236746 
185 20.69 5.00 Male False Sun  Dinner 5 0.241663 
51 10.29 2.60 Female False Sun  Dinner 2 0.252672 
149 7.51 2.00 Male False Thur Lunch 2 0.266312 
232 11.61 3.39 Male False Sat  Dinner 2 0.291990 

True 109 14.31 4.00 Female True Sat  Dinner 2 0.279525 
183 23.17 6.50 Male True Sun  Dinner 4 0.280535 
67 3.07 1.00 Female True Sat  Dinner 1 0.325733 
178 9.60 4.00 Female True Sun  Dinner 2 0.416667 
172 7.25 5.15 Male True Sun  Dinner 2 0.710345 
만큼 좋은

있지만 : 그래서이 작품

def top_all(df): 
    return df.sort_index(by='tip_pct') 

tips.groupby('smoker').transform(top_all) 

을 대신 나는이 얻을 :

TypeError: Transform function invalid for data types 

을 왜? 그 변형은 입력으로 받아 들일 수있는 차원과 동일한 차원의 배열을 반환해야한다는 것을 알고 있습니다. 따라서 각 차원을 변경하지 않고 원래 DataFrame의 조각 (흡연자와 비 흡연자)을 정렬하는 요구 사항을 준수 할 것이라고 생각했습니다. . 아무도 왜 실패했는지 설명 할 수 있습니까?

답변

36

transform 잘 설명되어 있지 않지만 변환 함수가 전달되는 것은 전체 그룹이 데이터 프레임이 아니라 단일 그룹의 단일 열입니다. 나는 그것이 당신이하려고하는 것에 정말로 의미가 있다고는 생각하지 않으며, apply을 가진 당신의 솔루션은 괜찮습니다.

그래서 tips.groupby('smoker').transform(func)이라고 가정합니다. 그룹 1과 그룹 2라고하는 두 그룹이 있습니다. 변환은 func(group1)func(group2)을 호출하지 않습니다. 대신 func(group1['total_bill'])을 호출 한 다음 func(group1['tip']) 등을 호출 한 다음 func(group2['total_bill']), func(group2['total_bill'])을 호출합니다.

>>> print d 
    A B C 
0 -2 5 4 
1 1 -1 2 
2 0 2 1 
3 -3 1 2 
4 5 0 2 
>>> def foo(df): 
...  print ">>>" 
...  print df 
...  print "<<<" 
...  return df 
>>> print d.groupby('C').transform(foo) 
>>> 
2 0 
Name: A 
<<< 
>>> 
2 2 
Name: B 
<<< 
>>> 
1 1 
3 -3 
4 5 
Name: A 
<<< 
>>> 
1 -1 
3 1 
4 0 
Name: B 
# etc. 

당신은 foo 먼저 원래의 데이터 프레임의 C = 1 기 단지 열, 그 그룹의 다음 B 컬럼의 다음 컬럼으로 호출되는 것을 볼 수있다 : 여기 예제 C = 2 그룹 등.

변형이 무엇인지 생각하면 의미가 있습니다. 그룹에 변환 함수를 적용하기위한 것입니다. 그러나 일반적으로이 함수는 그룹 전체에 적용 할 때, 주어진 열에 만 적용 할 수 있습니다. 예를 들어 팬더 문서의 예는 transform을 사용하는 z 표준화에 대한 것입니다. 나이와 무게에 대한 열이있는 DataFrame이있는 경우 두 변수의 전반적인 평균과 관련하여 z 표준화하는 것은 의미가 없습니다. 그것은 수의 낱단의 전반적인 평균을 가지고 가기 위하여 무언가를 의미하지 않는다, 어떤은 나이이고 어떤은 무게이다. 평균 체중과 관련하여 평균 연령과 체중을 기준으로 연령을 z 표준화해야합니다. 이는 각 항목에 대해 개별적으로 변형하려고 함을 의미합니다.

기본적으로 여기서 변환을 사용할 필요가 없습니다. apply은 실제로 각 그룹에서 단일 DataFrame으로 작동하기 때문에 apply이 적절한 함수입니다. transform은 각 그룹의 각 열에서 작동합니다.

+1

우수 답변. 고마워요! –

+6

변환이 왜 그렇게 잘 문서화되지 않았습니까? 나를 미치게 해.비록 당신이 당신의 print statments를 당신이 함수에 넣었을 때 실제로 변환이 시리즈와 데이터 프레임처럼 컬럼을 전달하고있는 것처럼 보이기 때문에 당신이 꽤 옳았다 고 생각합니다. 정말 괴롭고 나는 무엇이 뒤에서 진행되고 있는지 정확하게 알고 싶지만 실제로 어떻게 변형이 구현되었는지에 대한 정보는 찾을 수 없습니다. –

관련 문제