Производительность стека и раскрытия стека pandas снижается после сжатия кадра данных и намного хуже, чем в data.table R - PullRequest
0 голосов
/ 23 декабря 2018

Этот вопрос касается повышения производительности Pandas во время операций укладки и снятия.

Проблема в том, что у меня большой фрейм данных (~ 2 ГБ).Я следовал за этим блогом , чтобы успешно сжать его до ~ 150 МБ.Тем не менее, моя операция стекирования и распаковки занимает бесконечное количество времени, так что мне нужно убить ядро ​​и перезапустить все.

Я также использовал пакет R's data.table, и он просто летает, то есть завершает операцию за <1 секунду. </p>

Я исследовал это на SO.Похоже, что некоторые люди указывали на map-reduce на производительность unstack в Dataframe - поток pandas , но я не уверен в этом по двум причинам:

  1. stack и unstack в несжатом виде отлично работает в pandas, но я не могу сделать это в своем исходном наборе данных из-за проблем с памятью.
  2. R * data.table легко (<1 секунда) конвертирует из длинного в широкоформатный формат.</li>

Мне удалось вырезать небольшой фид (5 МБ) для целей представления для SO.Канал был загружен в http://www.filedropper.com/ddataredact. Этот файл должен быть в состоянии воспроизвести проблему.

Вот мой pandas код:

import pandas as pd

#Added code to generate test data
data = {'ANDroid_Margin':{'type':'float','len':13347},
        'Name':{'type':'cat','len':71869},
        'Geo1':{'type':'cat','len':4},
        'Geo2':{'type':'cat','len':31},
        'Model':{'type':'cat','len':2}}

ddata_i = pd.DataFrame()
len_data =114348
#categorical
for colk,colv in data.items():
    print("Processing column:",colk)
    #Is the data type numeric?
    if data[colk]['type']=='cat':
        chars = string.digits + string.ascii_lowercase
        replacement_value = [
            "".join(
                [random.choice(chars) for i in range(5)]
            ) for j in range(data[colk]['len'])]

    else:
        replacement_value = np.random.uniform(
            low=0.0, high=20.0, size=(data[colk]['len'],))
    ddata_i[colk] = np.random.choice(
        replacement_value,size=len_data,replace = True)

#Unstack and Stack now. This will show the result quickly
ddata_i.groupby(["Name","Geo1","Geo2","Model"]).\
    sum().\
    unstack().\
    stack(dropna=False).\
    reset_index()

#Compress our data
ddata = ddata_i.copy()

df_obj = ddata.select_dtypes(include=['object']).copy()
for col in df_obj:
    df_obj.loc[:, col] = df_obj[col].astype('category')
ddata[df_obj.columns] = df_obj

df_obj = ddata.select_dtypes(include=['float']).copy()
for col in df_obj:
    df_obj.loc[:, col] = df_obj[col].astype('float')
ddata[df_obj.columns] = df_obj

#Let's quickly check whether compressed file is same as original file
assert ddata.shape==ddata_i.shape, "Output seems wrong"
assert ddata_i.ANDroid_Margin.sum()==ddata.ANDroid_Margin.sum(),"Sum isn't right"
for col in ["ANDroid_Margin","Name","Geo1","Geo2"]:
    assert sorted(list(ddata_i[col].unique()))==sorted(list(ddata[col].unique()))

#This will run forever
ddata.groupby(["Name","Geo1","Geo2","Model"]).\
    sum().\
    unstack().\
    stack(dropna=False).\
    reset_index()

Вы заметите, что операции укладки и разборки на ddata_i будут выполняться быстро, но не на сжатых ddata.Почему это так?

Кроме того, я заметил, что если я сжимаю object или float, то stack() и unstack() будут работать быстро.Только когда я делаю и то, и другое, проблема сохраняется.

Может кто-нибудь помочь мне понять, что мне не хватает?Как я могу исправить проблему с pandas выше?Я чувствую, что с такими большими проблемами с производительностью, как я могу написать готовый код на pandas?Буду признателен за ваши мысли.


Наконец, вот код R data.table.Я должен сказать, что data.table не только быстр, но мне не нужно проходить сжатие и распаковку.

df <- data.table::fread("ddata_redact.csv",
                        stringsAsFactors=FALSE,
                        data.table = TRUE, 
                        header = TRUE)

df1=data.table::dcast(df, Name + Geo1 + Geo2 ~ Model, 
                      value.var = "ANDroid_Margin",
                      fun.aggregate = sum)

Может кто-нибудь помочь мне понять, что мне не хватает?Как я могу исправить проблему с pandas выше?Я чувствую, что с такими большими проблемами с производительностью, как я могу написать готовый код в pandas?Буду признателен за ваши мысли.


Информация о системе Python:

sys.version_info
> sys.version_info(major=3, minor=6, micro=7, releaselevel='final', serial=0)

версия для панд

pd.__version__
> '0.23.4'

data.table

1.11.8

1 Ответ

0 голосов
/ 25 декабря 2018

Я разобрался с ответом.Проблема заключается в том, что нам нужно добавить observed = True, чтобы pandas не вычислял декартово произведение.

После сжатия мне пришлось запустить этот ...

ddata.groupby(["Name","Geo1","Geo2","Model",observed = True]).\
    sum().\
    unstack().\
    stack(dropna=False).\
    reset_index()
...