在具有 125,497,040 条记录的数据集上运行

数据挖掘 熊猫
2022-03-10 21:31:46

我正在尝试运行add_datepart()它将 df 列从 datetime64 转换为许多列

年','月','周','日','Dayofweek','Dayofyear','Ismonthend','Ismonthstart','Isquarterend','Isquarterstart','Isyearend','Isyearstart'。ETC

我使用的是Grocery Sales dataset我相信的总日期是 125497040。我应该怎么做才能运行这个操作?

每次我运行这段代码。内核死机(内存不足 17.2 GB RAM)

所以我试着把这个数据框分解成更小的部分,然后运行add_datepart,但结果还是一样

我写了这段代码

def add_datepart_large(temp_df, size):
    list_df = [temp_df[i:i+size] for i in range(0,temp_df.shape[0],size)]
    for i in range(len(list_df)): add_datepart(list_df[i], 'date')
    return pd.concat(list_df)

final_df = add_datepart_large(df_all, 100000)

如果在运行此代码后,内核会死掉。怎么了?

4个回答

对于 1.27 亿行,最好在 DB 上执行数据准备。这将是一个 select + insert 查询,不需要将整个数据加载到内存中。

SELECT YEAR(date) AS 'year', MONTH(date) AS 'month'
 FROM data

编辑:一旦你开始训练/验证,即使这样,最好从数据库加载几批(一次)。大多数框架都支持这一点。

敌人示例:https ://github.com/keras-team/keras/issues/107

我不能说如何解决这个问题是 Pandas,而不必重新调整解决问题的方法(由于数据的大小)。

看看python数据表包,它就像一个在内存中运行的数据库,对于更大的数据帧性能更高,Pandas 可能会开始崩溃。它消耗更少的内存,并且在内部像数据库一样工作。

我还应该提到Dask,它是 Pandas 的分布式版本,它可能比 Pandas 本身更好地处理大量数据。

这里有两个建议:

看起来您的函数单独调用数据框中add_datepart的每一,这将引入大量开销。相反,您可以尝试拆分df_all成块(例如tmp_dfs = [df_all.iloc[i:i+size] for i in range(...)]),然后应用add_datepart到每个,然后将块连接在一起。这至少会减少开销,尽管 130 M 行对于在个人机器上运行的 Pandas 来说相当大。

Dask 是一个库,它或多或少地为 Pandas 数据帧提供了替代品,旨在处理非常大的数据集。我没有用你的数据集测试它,但它可能很简单

import dask.dataframe as dd
df_all = dd.read_csv(...) # Whatever arguments you used for pd.read_csv
add_datepart(df_all)

Dask 实际上只是为常规 Pandas 数据帧提供了一个包装器,所以如果您遇到 Dask 无法自动处理的情况,您可以随时使用map_partitions.

  • 循环读取磁盘中的数据

对于 pd.read_csv(..., chunksize=10^6) 中的块

  • 将您的函数应用于 DataFrame
  • 以“a”模式存储您的 DataFrame

chunk.to_csv(..., mode="a")