【问题标题】:numpy broadcasting on pandas dataframe gives memory errorPandas 数据帧上的 numpy 广播会导致内存错误
【发布时间】:2021-09-23 06:06:44
【问题描述】:

我有两个数据框。数据框 A 的形状为 (1269345,5),数据框 B 的形状为 (18583586, 3)。

数据框 A 如下所示:

Name.   gender     start_coordinate    end_coordinate    ID      
Peter     M             30                  150           1      
Hugo      M            4500                6000           2      
Jennie    F             300                 700           3   

数据框(B)看起来像

ID_sim.  position      string      
  1         89            aa      
  4         568            bb     
  5        938437         cc

我想提取行并制作两个数据框,其中数据框 B 中的位置列落在数据框 A 中的区间(由 start_coordinate 和 end_coordinate 列指定)中。因此生成的数据框如下所示:

###Final dataframe A
Name.   gender     start_coordinate    end_coordinate    ID      
Peter     M             30                  150           1 
Jennie    F             300                 700           3  


###Final dataframe B

ID_sim.    position     string          
   1          89           aa 
   4          568           bb 

我尝试像这样使用 numpy 广播:

s, e = dfA[['start_coordinate', 'end_coordinate']].to_numpy().T
p = dfB['position'].to_numpy()[:, None]

dfB[((p >= s) & (p <= e)).any(1)]

但这给了我以下错误:

MemoryError: 无法为形状为 (18583586, 160711) 且数据类型为 bool 的数组分配 2.72 TiB

我认为这是因为当我尝试广播时,我的 numpy 变得非常大。考虑到我的数据帧非常大,如何在没有 numpy 广播的情况下完成我的任务。我们将不胜感激。

【问题讨论】:

    标签: python-3.x pandas numpy-ndarray


    【解决方案1】:

    这可能是由于您的系统过度使用模式所致。

    默认为0,

    启发式过度使用处理。地址空间的明显过度使用 被拒绝。用于典型系统。它确保了一个严重的狂野 分配失败,同时允许过度使用以减少交换使用。这 在这种模式下,root 可以分配稍微多一点的内存。这是 默认。

    通过运行以下命令来检查您当前的过度使用模式

    $ cat /proc/sys/vm/overcommit_memory
    0
    

    在这种情况下,您正在分配

    > 156816 * 36 * 53806 / 1024.0**3
    282.8939827680588
    

    ~282 GB,内核说得很好,显然我不可能向它提交这么多物理页面,它拒绝分配。

    如果您(以 root 身份)运行:

    $ echo 1 > /proc/sys/vm/overcommit_memory 
    

    这将启用“始终过量使用”模式,您会发现系统确实允许您进行分配,无论它有多大(至少在 64 位内存寻址范围内)。

    我自己在具有 32 GB RAM 的机器上对此进行了测试。在过度使用模式 0 下,我也遇到了 MemoryError,但在将其更改回 1 后它可以工作:

    >>> import numpy as np 
    >>> a = np.zeros((156816, 36, 53806), dtype='uint8')
    >>> a.nbytes
    
    303755101056
    

    然后您可以继续写入阵列中的任何位置,系统只会在您明确写入该页面时分配物理页面。因此,您可以小心地将其用于稀疏数组。

    【讨论】:

    • 我做不到。系统拒绝我这样做。不过谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-07-04
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    相关资源
    最近更新 更多