python - pandas stack and unstack performance reduced after dataframe compression 并且比 R 的 data.table 差很多

标签 python r pandas data.table

这个问题是关于在堆叠和取消堆叠操作期间提升 Pandas 的性能。

问题是我有一个大数据框 (~2GB)。我关注了this blog成功将其压缩到 ~150MB。但是,我的入栈和出栈操作会花费无限长的时间,以至于我必须终止内核并重新启动所有程序。

我也用过R的data.table包,飞起来了,<1秒就完成了。

我在 SO 上对此进行了研究。似乎有人在 Dataframe unstack performance - pandas 上指向 map-reduce线程,但我不确定它有两个原因:

  1. stackunstack 在未压缩的情况下在 pandas 中运行良好,但由于内存问题,我无法在我的原始数据集上执行此操作。
  2. R 的 data.table 很容易(<1 秒)从长格式转换为宽格式。

为了 SO 的展示目的,我设法剪切了一个小提要 (5MB)。提要已上传至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 则不然。这是为什么?

此外,我注意到如果我压缩 objectfloat,则 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)

Pandas 版

pd.__version__
> '0.23.4'

数据表

1.11.8

最佳答案

我想出了答案。问题是我们需要添加 observed = True 以防止 pandas 计算笛卡尔积。

压缩后,我必须运行这个...

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

关于python - pandas stack and unstack performance reduced after dataframe compression 并且比 R 的 data.table 差很多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53901363/

相关文章:

python - 消除 numpy 中的循环 - 正确的广播

python - Python 中的树似乎构建不正确

javascript - Django:更改 javascript 函数内的字体颜色

从具有多个级别的箱形图中删除空级别

r - 如何在R中绘制3D堆叠直方图?

python - 使用变量在循环中从 DataFrame 中提取数据

python - 前 N 行,直到找到值不为空

python - Keras 模型不学习

r - 基于两列字符串匹配的子集 R 数据框

python - Pandas GroupBy 和计算 Z-Score