2017-01-05 9 views
11

Я не понимаю, почему apply и transform возвращают разные типы данных при вызове в том же фрейме данных. То, как я объяснял две функции себе, прежде чем что-то пошло «apply, обрушивает данные, а transform делает то же самое, что и apply, но сохраняет исходный индекс и не рушится». Рассмотрим следующее.Pandas transform() vs apply()

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]}) 

Давайте определить те id S, которые имеют ненулевой элемент в столбце cat.

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

Отлично. Однако, если бы мы хотели создать столбец индикаторов, мы могли бы сделать следующее.

>>> 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 

Я не понимаю, почему DTYPE теперь int64 вместо булева возвращаемой функции any().

Когда я изменяю исходный фрейм данных, чтобы содержать некоторые булевы (обратите внимание, что нули остаются), подход преобразования возвращает логические значения в столбце object. Это дополнительная тайна для меня, поскольку все значения являются логическими, но они указаны как object, по-видимому, для соответствия dtype исходного столбца смешанного типа целых чисел и булевых элементов.

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 

Однако, когда я использую все логические значения, функция преобразования возвращает булевский столбец.

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 

Используя свои острые навыки распознавания образов, кажется, что dtype результирующего столбца отражает структуру исходного столбца. Я был бы признателен за любые подсказки о том, почему это происходит или что происходит под капотом в функции transform. Приветствия.

+0

'apply' не разрушится данные. 'apply' является гибким и может возвращать серию или dataframe любого размера. 'transform' всегда сохраняет количество строк для каждой группы. 'transform' также отправляет каждый отдельный столбец в виде серии вызывающей функции. 'apply' отправляет весь файл данных в вызывающую функцию. –

+2

[related] (http://stackoverflow.com/a/38579754/2336654) – piRSquared

+0

Aha! Спасибо @piRSquared. Думаю, я понимаю, почему это происходит после прочтения этого комментария и изучения исходного кода. – 3novak

ответ

6

Похоже SeriesGroupBy.transform() пытается бросить результат DTYPE одному и тому же, как оригинал столбец имеет, но DataFrameGroupBy.transform() не кажется, сделать это:

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