Оптимальный способ сгладить длинный фрейм данных с помощью или без pivot

#python #pandas #dataframe #optimization #pivot-table

#python #pandas #фрейм данных #оптимизация #сводная таблица

Вопрос:

У меня есть длинный фрейм данных для сглаживания. Фрейм данных выглядит следующим образом. Я хочу сгладить эту таблицу, использовать referenceDate companyId в качестве индекса, столбцы должны иметь два слоя, первый data_item — это, а второй будет N . Я знаю, что pd.pivot решит проблему.

  --------------- ----------- ----------- --- ------- 
| referenceDate | CompanyId | data_item | N | value |
 --------------- ----------- ----------- --- ------- 
| 2020-01-31    |         1 | A         | 1 | 0.1   |
| 2020-01-31    |         2 | A         | 2 | 0.2   |
| 2020-01-31    |         3 | A         | 3 | 0.3   |
 --------------- ----------- ----------- --- ------- 
  

Однако,

 df = pd.pivot(df, values='value', index=['referenceDate', 'companyId'], columns=['data_item', 'N'])
  

всегда выдает ошибку ValueError

 Traceback (most recent call last):
  File "C:Users\PycharmProjectsvenvs\libsite-packagesIPythoncoreinteractiveshell.py", line 3343, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-56-3738f20d42ed>", line 1, in <module>
    df = pd.pivot(df, values='value', index=['referenceDate', 'companyId'], columns=['data_item', 'N'])
  File "C:Users\PycharmProjectsvenvs\libsite-packagespandascorereshapepivot.py", line 429, in pivot
    indexed = data._constructor_sliced(data[values].values, index=index)
  File "C:Users\PycharmProjectsvenvs\libsite-packagespandascoreseries.py", line 302, in __init__
    "index implies {ind}".format(val=len(data), ind=len(index))
ValueError: Length of passed values is 239689, index implies 2
  

pd.pivot_table работает хорошо, но в этом случае мне не нужна агрегация, и я также обеспокоен производительностью, когда фрейм данных имеет большой размер (в миллиардах строк). На самом деле у меня здесь ошибка памяти, в нем говорится, что не удается выделить 1.xxGB для массива numpy, когда я выполнил это:

 df = pd.pivot_table(df, values='value', index=['referenceDate', 'companyId'],
                                            columns=['data_item', 'N'], aggfunc='first')
  

Мне было интересно, почему pd.pivot сбой здесь и рядом pd.pivot и pd.pivot_table , если есть оптимальное решение (требующее наименьшего объема памяти) для моей проблемы?

Комментарии:

1. На какой версии pandas вы работаете? Вы можете проверить с помощью pd.__version__

2. @DavidErickson 0.25.3, это было из этого проекта requirements.txt . Будет ли это проблемой?

3. смотрите мой ответ. Я почти уверен, что это связано с наличием более старой версии pandas, в которой pivot были ошибки.

4. пожалуйста, примите один из ответов в качестве решения, нажав на галочку рядом с моим ответом. Спасибо!

Ответ №1:

Попробуйте перейти на более новую версию pandas, если вы можете временно или постоянно, поскольку pivot в более ранних версиях pandas есть ошибки.

Например, вы можете сделать это: pip install pandas==1.1.3 обновить до определенной версии, где они исправлены pivot .

 pip install pandas==1.1.3
# then restart the kernel

import pandas as pd
# df = ....
df = pd.pivot(df, values='value', index=['referenceDate', 'CompanyId'], columns=['data_item', 'N'])
df
Out[1]: 
data_item                  A          
N                          1    2    3
referenceDate CompanyId               
2020-01-31    1          0.1  NaN  NaN
              2          NaN  0.2  NaN
              3          NaN  NaN  0.3
  

Затем вы всегда можете вернуться к pip install pandas==0.25.3 . Вы можете сделать все это из своего блокнота jupyter. Обязательно перезапускайте ядро при каждом переключении версий.

Моя текущая версия pandas 1.0.1 , поэтому я также получаю ту же ошибку!

 pip install pandas==1.0.1
#restart kernel

import pandas as pd
#df = ...
df = pd.pivot(df, values='value', index=['referenceDate', 'CompanyId'], columns=['data_item', 'N'])
df
  

Ошибка:

 ValueError                                Traceback (most recent call last)
<ipython-input-2-11248dbe0eba> in <module>
      1 df = d.copy()
----> 2 df = pd.pivot(df, values='value', index=['referenceDate', 'CompanyId'], columns=['data_item', 'N'])
      3 df

C:Usersdavid.ericksonAnaconda3libsite-packagespandascorereshapepivot.py in pivot(data, index, columns, values)
    445             )
    446         else:
--> 447             indexed = data._constructor_sliced(data[values].values, index=index)
    448     return indexed.unstack(columns)
    449 

C:Usersdavid.ericksonAnaconda3libsite-packagespandascoreseries.py in __init__(self, data, index, dtype, name, copy, fastpath)
    290                     if len(index) != len(data):
    291                         raise ValueError(
--> 292                             f"Length of passed values is {len(data)}, "
    293                             f"index implies {len(index)}."
    294                         )

ValueError: Length of passed values is 3, index implies 2.