2017-01-05 12 views
11

Nie rozumiem, dlaczego apply i transform zwracają różne dtypes po wywołaniu na tej samej ramce danych. Sposób, w jaki wyjaśniłem sobie dwie funkcje, przeszedł coś w rodzaju: "apply zwija dane, a transform robi dokładnie to samo, co apply, ale zachowuje oryginalny indeks i nie zwija się." Rozważ następujące.Panda transformacja() kontra zastosowanie()

df = pd.DataFrame({'id': [1,1,1,2,2,2,2,3,3,4], 
        'cat': [1,1,0,0,1,0,0,0,0,1]}) 

Niech zidentyfikować te id s, które mają niezerową wartość w kolumnie cat.

>>> df.groupby('id')['cat'].apply(lambda x: (x == 1).any()) 
id 
1  True 
2  True 
3 False 
4  True 
Name: cat, dtype: bool 

Świetnie. Jeśli jednak chcielibyśmy utworzyć kolumnę wskaźnikową, moglibyśmy wykonać następujące czynności.

>>> df.groupby('id')['cat'].transform(lambda x: (x == 1).any()) 
0 1 
1 1 
2 1 
3 1 
4 1 
5 1 
6 1 
7 0 
8 0 
9 1 
Name: cat, dtype: int64 

Nie rozumiem, dlaczego jest teraz int64 dtype zamiast Boolean zwracanych przez funkcję any().

Kiedy zmieniam oryginalną ramkę danych tak, aby zawierała wartości binarne (należy pamiętać, że zera pozostały), metoda przekształcania zwraca wartości logiczne w kolumnie object. Jest to dla mnie dodatkowa tajemnica, ponieważ wszystkie wartości są wartościami logicznymi, ale są one wymienione jako object najwyraźniej w celu dopasowania do dtype pierwotnej kolumny liczb całkowitych i boolean mieszanych.

df = pd.DataFrame({'id': [1,1,1,2,2,2,2,3,3,4], 
        'cat': [True,True,0,0,True,0,0,0,0,True]}) 

>>> df.groupby('id')['cat'].transform(lambda x: (x == 1).any()) 
0  True 
1  True 
2  True 
3  True 
4  True 
5  True 
6  True 
7 False 
8 False 
9  True 
Name: cat, dtype: object 

Jednak, gdy używam wszystkich wartości logicznych, funkcja transformacji zwraca kolumnę binarną.

df = pd.DataFrame({'id': [1,1,1,2,2,2,2,3,3,4], 
        'cat': [True,True,False,False,True,False,False,False,False,True]}) 

>>> df.groupby('id')['cat'].transform(lambda x: (x == 1).any()) 
0  True 
1  True 
2  True 
3  True 
4  True 
5  True 
6  True 
7 False 
8 False 
9  True 
Name: cat, dtype: bool 

Korzystanie moje ostre umiejętności rozpoznawania wzorów, wydaje się, że dtype powstałego kolumnie lusterka oryginalnego kolumnie. Byłbym wdzięczny za wszelkie wskazówki, dlaczego tak się dzieje lub co dzieje się pod maską w funkcji transform. Twoje zdrowie.

+0

'apply' nie zawali dane. 'apply' jest elastyczne i może zwrócić serię lub ramkę danych o dowolnym rozmiarze. "transformacja" zawsze zachowuje liczbę wierszy dla każdej grupy. 'transform' również wysyła każdą kolumnę jako serię do funkcji wywołującej. 'apply' wysyła całą ramkę danych do funkcji wywołującej. –

+2

[powiązane] (http://stackoverflow.com/a/38579754/2336654) – piRSquared

+0

Aha! Dziękujemy @piRSquared. Myślę, że lepiej rozumiem, dlaczego tak się dzieje po przeczytaniu tego komentarza i spojrzeniu na kod źródłowy. – 3novak

Odpowiedz

6

Wygląda SeriesGroupBy.transform() próbuje rzucić dtype rezultatu, który ma taki sam jak oryginalne kolumna ma, ale DataFrameGroupBy.transform() nie wydaje się, aby to zrobić:

In [139]: df.groupby('id')['cat'].transform(lambda x: (x == 1).any()) 
Out[139]: 
0 1 
1 1 
2 1 
3 1 
4 1 
5 1 
6 1 
7 0 
8 0 
9 1 
Name: cat, dtype: int64 

#       v  v 
In [140]: df.groupby('id')[['cat']].transform(lambda x: (x == 1).any()) 
Out[140]: 
    cat 
0 True 
1 True 
2 True 
3 True 
4 True 
5 True 
6 True 
7 False 
8 False 
9 True 

In [141]: df.dtypes 
Out[141]: 
cat int64 
id  int64 
dtype: object