Этот вопрос касается повышения производительности Pandas во время операций укладки и снятия.
Проблема в том, что у меня большой фрейм данных (~ 2 ГБ).Я следовал за этим блогом , чтобы успешно сжать его до ~ 150 МБ.Тем не менее, моя операция стекирования и распаковки занимает бесконечное количество времени, так что мне нужно убить ядро и перезапустить все.
Я также использовал пакет R's data.table
, и он просто летает, то есть завершает операцию за <1 секунду. </p>
Я исследовал это на SO.Похоже, что некоторые люди указывали на map-reduce
на производительность unstack в Dataframe - поток pandas , но я не уверен в этом по двум причинам:
stack
и unstack
в несжатом виде отлично работает в pandas
, но я не могу сделать это в своем исходном наборе данных из-за проблем с памятью. - 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