Каков наилучший способ сохранить данные для столбцов, которые не могут быть агрегированы во время групповой операции на фрейме данных pandas? - PullRequest
4 голосов
/ 06 марта 2020

Pandas Фреймы данных отлично подходят для хранения неоднородных типов данных, а метод groupby добавляет большую гибкость для агрегирования данных; однако я часто хотел бы сохранить базовые данные, которые не могут быть агрегированы после выполнения операции группировки.

Пример :

Давайте поработаем со следующим фреймом данных:

df_cars = pd.DataFrame({
          'brand': ['Porsche', 'Porsche', 'Porsche', 'BMW' ,'BMW' ,'BMW'],
          'model': ['911 GT3', '911', '911', 'M3', 'M3', 'M3', ],
          'speed(mph)': [100, 120, 110, 70, 80, 90]})

Если бы я запускал следующий код:

df_cars.groupby('brand').mean()

Я бы получил среднюю скорость (миль в час) для каждого бренда; однако я бы потерял базовые данные из столбцов модели и бренда.

Чтобы сохранить эту информацию и выполнить те же вычисления среднего значения, мне нужно было бы вместо этого выполнить следующий код:

df_cars.groupby('brand').agg({
                        'speed(mph)':'mean', 
                        'model': lambda x: x.iloc[0] if x.nunique() == 1 else list(x),
                        'brand': lambda x: x.iloc[0] if x.nunique() == 1 else list(x)
                        })

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

Является ли это наиболее эффективным способом сохранения этой информации? Кроме того, почему это не вариант в стандартной реализации groupby для более простого хранения данных, которые не могут быть агрегированы?

1 Ответ

3 голосов
/ 06 марта 2020

Прежде всего, когда вы агрегируете данные, по определению вы потеряете информацию, поскольку вы суммируете свой набор данных.

Тем не менее, я вижу, что у вас есть два варианта:

1. упростите ваш код и примените правильные методы:

df_cars.groupby('brand', as_index=False).agg({
    'speed(mph)': 'mean',
    'model': 'unique'
})

     brand  speed(mph)           model
0      BMW          80            [M3]
1  Porsche         110  [911 GT3, 911]

Или, если вы не хотите, чтобы столбец типа вашего объекта в списке:

df_cars.groupby('brand', as_index=False).agg({
    'speed(mph)': 'mean',
    'model': lambda x: ','.join(np.unique(x))
})

     brand  speed(mph)        model
0      BMW          80           M3
1  Porsche         110  911,911 GT3

2. Разделите данные по типу столбцов и примените простые агрегации:

, это работает для больших фреймов данных с несколькими объектами и цифрами c столбцы

df_cars = df_cars.set_index('brand')
text = df_cars.select_dtypes('object')
numeric = df_cars.select_dtypes(exclude='object')

g1 = text.groupby('brand')
g2 = numeric.groupby('brand')

dfn = g1.agg(np.unique).join(g2.mean()).reset_index()

     brand           model  speed(mph)
0      BMW              M3          80
1  Porsche  [911, 911 GT3]         110
...