groupby python TypeError: неупорядоченные типы: tuple () <str ()

python-3.x pandas

1223 просмотра

1 ответ

Первоначально я написал некоторый код на Python 2.7, но теперь я перешел на Python 3.5. Я хочу объединить числовые данные из пары столбцов и группировать их по остальным или хотя бы по одному.

Вот мой исходный фрейм данных "testdf":

testdf
     PROD_TAG   BRAND   Market         ('VAL', 'Per1')  ('VAL', 'Per2')
        P_1       A     Modern Trade         4.3           0.155
        P_2       A     Traditional Trade    5.7           0
        P_3       B     Modern Trade         10.0          11.2
        P_3       B     Traditional Trade    8.7           6.3
        P_4       C     Modern Trade         12.1          12.3
        P_5       D     Modern Trade         8.0           7.0

Последние два заголовка столбца являются кортежами (спасибо капитану, очевидно). Per1 и Per2 означает соответствующие периоды.

Я хочу выполнить строку кода, которая работала ранее на Python 2.7:

testdf=testdf.groupby(['BRAND'])[('VAL','P1'),('VAL','P2')].sum()

Это не работает из-за типа кортежа заголовков столбцов и повышает:

TypeError: unorderable types: tuple() < str()

Теперь, если я переименую заголовки столбцов так:

testdf.columns=['PROD_TAG', 'BRAND', 'Market', 'VAL-P1', 'VAL-P2']

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

testdf1=testdf.groupby(['BRAND'])['VAL-P1','VAL-P2'].sum()

и получите в итоге:

BRAND     ('VAL', 'Per1')   ('VAL', 'Per2')
  A            10.0              0.155
  B            18.7              17.5
  C            12.1              12.3
  D            8.0               7.0

Самое странное здесь то, что, если я использую .mean()вместо этого .sum(), min() or .max(), все отлично работает даже с кортежами.

Кто-нибудь может объяснить мне, как я могу заставить такие агрегаты с именами столбцов кортежа работать на Python 3.5?

Автор: Dmitriy Fialkovskiy Источник Размещён: 08.11.2019 11:05

Ответы (1)


2 плюса

Решение

Я думаю, что вам нужно использовать groupby.aggи передать функцию для суммирования суммы каждой группы, как показано:

df = pd.DataFrame({'PROD_TAG':["P_1", "P_2", "P_3", "P_3", "P_4", "P_5"],
                   'BRAND':["A", "A", "B", "B", "C", "D"],
                   'Market':["Modern Trade", "Traditional Trade",   \
                   "Modern Trade", "Traditional Trade", "Modern Trade", "Modern Trade"],
                   ('VAL','Per1'):[4.3, 5.7, 10.0, 8.7, 12.1, 8.0],
                   ('VAL','Per2'):[0.155, 0, 11.2, 6.3, 12.3, 7.0]})

type(df[('VAL','Per1')].name)
#<class 'tuple'>

df.groupby(['BRAND'])[('VAL','Per1'), ('VAL','Per2')].agg(lambda x: x.sum())

       (VAL, Per1)  (VAL, Per2)
BRAND                          
A             10.0        0.155
B             18.7       17.500
C             12.1       12.300
D              8.0        7.000

В качестве альтернативы, индекс не сбрасывается, а столбцы группировщика преобразуются. Таким образом, вы можете избавиться от TypeErrorнесоответствия имен столбцов [ tuple/str].

df.groupby(['BRAND'], as_index=False)[('VAL','Per1'), ('VAL','Per2')].sum()

  BRAND  (VAL, Per1)  (VAL, Per2)
0     A         10.0        0.155
1     B         18.7       17.500
2     C         12.1       12.300
3     D          8.0        7.000

Но если вы renameиспользуете tupleстолбцы string, вы можете продолжить, как и раньше, без использования aggфункций:

df.rename(index=str, columns={('VAL','Per1'): "('VAL','Per1')",      \
                              ('VAL','Per2'): "('VAL','Per2')"}, inplace=True)

type(df["('VAL','Per1')"].name)
#<class 'str'>

df.groupby(['BRAND'])["('VAL','Per1')","('VAL','Per2')"].sum()

       ('VAL','Per1')  ('VAL','Per2')
BRAND                                
A                10.0           0.155
B                18.7          17.500
C                12.1          12.300
D                 8.0           7.000

Примечание: протестировано вPython 3.5

Автор: Nickil Maveli Размещён: 20.08.2016 11:04
Вопросы из категории :
32x32