Spec-Zone.ru › pandas 0.25

Преобразование формы и сводные таблицы

Преобразование формы, сворачивая объекты DataFrame

../_images/reshaping_pivot.png

Данные часто хранятся в так называемом «упакованном» или «записях» формате:

In [1]: df
Out[1]: 
         date variable     value
0  2000-01-03        A  0.469112
1  2000-01-04        A -0.282863
2  2000-01-05        A -1.509059
3  2000-01-03        B -1.135632
4  2000-01-04        B  1.212112
5  2000-01-05        B -0.173215
6  2000-01-03        C  0.119209
7  2000-01-04        C -1.044236
8  2000-01-05        C -0.861849
9  2000-01-03        D -2.104569
10 2000-01-04        D -0.494929
11 2000-01-05        D  1.071804

Для любознательных вот как было создано приведенное выше DataFrame:

import pandas.util.testing as tm

tm.N = 3


def unpivot(frame):
    N, K = frame.shape
    data = {'value': frame.to_numpy().ravel('F'),
            'variable': np.asarray(frame.columns).repeat(N),
            'date': np.tile(np.asarray(frame.index), K)}
    return pd.DataFrame(data, columns=['date', 'variable', 'value'])


df = unpivot(tm.makeTimeDataFrame())

Чтобы выбрать всё для переменной A, можно сделать следующее:

In [2]: df[df['variable'] == 'A']
Out[2]: 
        date variable     value
0 2000-01-03        A  0.469112
1 2000-01-04        A -0.282863
2 2000-01-05        A -1.509059

Но предположим, что мы хотим выполнить операции с временными рядами с переменными. Лучшим представлением будет такое, где columns являются уникальными переменными, а index дат определяет отдельные наблюдения. Чтобы преобразовать данные в этот вид, мы используем метод DataFrame.pivot() (также реализован как функция верхнего уровня pivot()):

In [3]: df.pivot(index='date', columns='variable', values='value')
Out[3]: 
variable           A         B         C         D
date                                              
2000-01-03  0.469112 -1.135632  0.119209 -2.104569
2000-01-04 -0.282863  1.212112 -1.044236 -0.494929
2000-01-05 -1.509059 -0.173215 -0.861849  1.071804

Если аргумент values опущен, а входной DataFrame имеет более одной колонки значений, которые не используются в качестве колонок или индексов для ввода в pivot, то получившийся «свернутый» DataFrame будет содержать многоуровневые колонки, самый верхний уровень которых указывает на соответствующую колонку значений:

In [4]: df['value2'] = df['value'] * 2

In [5]: pivoted = df.pivot(index='date', columns='variable')

In [6]: pivoted
Out[6]: 
               value                                  value2                              
variable           A         B         C         D         A         B         C         D
date                                                                                      
2000-01-03  0.469112 -1.135632  0.119209 -2.104569  0.938225 -2.271265  0.238417 -4.209138
2000-01-04 -0.282863  1.212112 -1.044236 -0.494929 -0.565727  2.424224 -2.088472 -0.989859
2000-01-05 -1.509059 -0.173215 -0.861849  1.071804 -3.018117 -0.346429 -1.723698  2.143608

Затем вы можете выбрать подмножества из свернутого DataFrame:

In [7]: pivoted['value2']
Out[7]: 
variable           A         B         C         D
date                                              
2000-01-03  0.938225 -2.271265  0.238417 -4.209138
2000-01-04 -0.565727  2.424224 -2.088472 -0.989859
2000-01-05 -3.018117 -0.346429 -1.723698  2.143608

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

Примечание

pivot() вызовет ошибку ValueError: Index contains duplicate entries, cannot reshape, если пара индекс/колонка не уникальна. В этом случае рассмотрите использование pivot_table(), которое является обобщением сворачивания и может обрабатывать дублирующие значения для одной пары индекс/колонка.

Преобразование формы путем стекирования и расстекивания

../_images/reshaping_stack.png

Тесно связаны с методом pivot() родственные методы stack() и unstack(), доступные для Series и DataFrame. Эти методы предназначены для совместной работы с MultiIndex объектами (см. раздел многоуровневого индексирования). Вот что в основном делают эти методы:

  • stack: «свертывает» уровень (возможно, многоуровневых) меток колонок, возвращая DataFrame с индексом с новым внутренним уровнем меток строк.
  • unstack: (обратная операция к stack) «свертывает» уровень (возможно, многоуровневого) индекса строк в ось колонок, создавая преобразованный DataFrame с новым внутренним уровнем меток колонок.
../_images/reshaping_unstack.png

Самый понятный способ объяснить — на примере. Возьмем предыдущий набор данных из раздела многоуровневого индексирования:

In [8]: tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
   ...:                      'foo', 'foo', 'qux', 'qux'],
   ...:                     ['one', 'two', 'one', 'two',
   ...:                      'one', 'two', 'one', 'two']]))
   ...: 

In [9]: index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])

In [10]: df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])

In [11]: df2 = df[:4]

In [12]: df2
Out[12]: 
                     A         B
first second                    
bar   one     0.721555 -0.706771
      two    -1.039575  0.271860
baz   one    -0.424972  0.567020
      two     0.276232 -1.087401

Функция stack «сжимает» уровень в колонках DataFrame, чтобы получить:

  • Series, в случае простого индекса колонок.
  • DataFrame, в случае MultiIndex в колонках.

Если у колонок есть MultiIndex, вы можете выбрать, какой уровень стекать. Уровень стекания становится новым самым низким уровнем в MultiIndex по колонке:

In [13]: stacked = df2.stack()

In [14]: stacked
Out[14]: 
first  second   
bar    one     A    0.721555
               B   -0.706771
       two     A   -1.039575
               B    0.271860
baz    one     A   -0.424972
               B    0.567020
       two     A    0.276232
               B   -1.087401
dtype: float64

В случае «упакованного» DataFrame или Series (имеющего MultiIndex в качестве index), обратная операция к stack — это unstack, которая по умолчанию расстекивает последний уровень:

In [15]: stacked.unstack()
Out[15]: 
                     A         B
first second                    
bar   one     0.721555 -0.706771
      two    -1.039575  0.271860
baz   one    -0.424972  0.567020
      two     0.276232 -1.087401

In [16]: stacked.unstack(1)

© 2008–2012, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
Licensed under the 3-clause BSD License.
https://pandas.pydata.org/pandas-docs/version/0.25.0/user_guide/reshaping.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API