当前位置: 首页 > 面试题库 >

可以memmap pandas系列。数据框呢?

郑曜灿
2023-03-14
问题内容

似乎我可以通过创建mmap’d ndarray并使用它来初始化python系列的memmap底层数据。

        def assert_readonly(iloc):
           try:
               iloc[0] = 999 # Should be non-editable
               raise Exception("MUST BE READ ONLY (1)")
           except ValueError as e:
               assert "read-only" in e.message

        # Original ndarray
        n = 1000
        _arr = np.arange(0,1000, dtype=float)

        # Convert it to a memmap
        mm = np.memmap(filename, mode='w+', shape=_arr.shape, dtype=_arr.dtype)
        mm[:] = _arr[:]
        del _arr
        mm.flush()
        mm.flags['WRITEABLE'] = False  # Make immutable!

        # Wrap as a series
        s = pd.Series(mm, name="a")
        assert_readonly(s.iloc)

成功!似乎它s由只读的内存映射ndarray支持。我可以对DataFrame做同样的事情吗?以下失败

        df = pd.DataFrame(s, copy=False, columns=['a'])
        assert_readonly(df["a"]) # Fails

以下成功,但仅适用于一列:

        df = pd.DataFrame(mm.reshape(len(mm,1)), columns=['a'], copy=False)
        assert_readonly(df["a"]) # Succeeds

…这样我 就可以 不复制而制作DF。但是,这仅适用于一列,我想要很多。我发现了用于组合1列DF的方法:pd.concat(.. copy =
False),pd.merge(copy = False),…产生副本。

我有成千上万的大列作为数据文件,一次只需要几列。我希望能够将它们的mmap表示形式放置在上面的DataFrame中。可能吗?

Pandas文档使我们很难猜测这里到底发生了什么-尽管它确实说一个DataFrame
“可以认为是Series对象的类似dict的容器”。。我开始不再是这种情况了。

我宁愿不需要HD5来解决这个问题。


问题答案:

好…经过大量挖掘,这是怎么回事。PandasDataFrame使用BlockManager该类在内部组织数据。与文档相反,DataFrame不是系列的集合,而是
类似dtyped矩阵的集合
。BlockManger将所有float列组合在一起,将所有int列组合在一起,等等…,并且它们的内存(据我所知)保持在一起。

如果提供单个ndarray矩阵(单个类型),则无需复制内存即可做到这一点。请注意,BlockManager(理论上)还支持在其构造中不复制混合类型数据,因为可能不必将此输入复制到相同类型的块中。但是,如果单个矩阵是数据参数,则DataFrame构造函数不会仅进行复制。

简而言之,如果您将混合类型或多个数组作为构造函数的输入,或者为dict提供单个数组,则您在Pandas中不走运,DataFrame的默认BlockManager将复制您的数据。

无论如何,解决此问题的一种方法是强制BlockManager不要按类型合并,而是将每列保留为单独的“块”。所以,有了猴子修补魔法…

        from pandas.core.internals import BlockManager
        class BlockManagerUnconsolidated(BlockManager):
            def __init__(self, *args, **kwargs):
                BlockManager.__init__(self, *args, **kwargs)
                self._is_consolidated = False
                self._known_consolidated = False

            def _consolidate_inplace(self): pass
            def _consolidate(self): return self.blocks


        def df_from_arrays(arrays, columns, index):
            from pandas.core.internals import make_block
            def gen():
                _len = None
                p = 0
                for a in arrays:
                    if _len is None:
                        _len = len(a)
                        assert len(index) == _len
                    assert _len == len(a)
                    yield make_block(values=a.reshape((1,_len)), placement=(p,))
                    p+=1

            blocks = tuple(gen())
            mgr = BlockManagerUnconsolidated(blocks=blocks, axes=[columns, index])
            return pd.DataFrame(mgr, copy=False)

如果指定copy = False,则DataFrame或BlockManger最好具有consolidate = False(或假设有此行为)。

去测试:

    def assert_readonly(iloc):
       try:
           iloc[0] = 999 # Should be non-editable
           raise Exception("MUST BE READ ONLY (1)")
       except ValueError as e:
           assert "read-only" in e.message

    # Original ndarray
    n = 1000
    _arr = np.arange(0,1000, dtype=float)

    # Convert it to a memmap
    mm = np.memmap(filename, mode='w+', shape=_arr.shape, dtype=_arr.dtype)
    mm[:] = _arr[:]
    del _arr
    mm.flush()
    mm.flags['WRITEABLE'] = False  # Make immutable!

        df = df_from_arrays(
            [mm, mm, mm],
            columns=['a', 'b', 'c'],
            index=range(len(mm)))
        assert_read_only(df["a"].iloc)
        assert_read_only(df["b"].iloc)
        assert_read_only(df["c"].iloc)

对于我来说,将BlockManager类似类型的数据保存在一起是否真的有实际的好处-在Pandas中的大多数操作都是按行标签或逐列进行操作-
这是DataFrame由于结构的异构通常仅通过其索引关联的列。尽管可行的是,他们在每个“块”中保留一个索引,但是如果索引在块中保留偏移量,则可以从中受益(如果是这种情况,那么他们应该按进行分组sizeof(dtype),我认为情况并非如此)。呵呵…

关于提供非复制构造函数的PR进行了一些讨论,但被放弃了。

看来有逐步淘汰BlockManager的明智计划,因此您的工作量很多。

另请参阅引擎盖下的熊猫,这对我很有帮助。



 类似资料:
  • 问题内容: 我有一个熊猫数据框: 其中包括系列对象: 指出了一些命令: 每个字典具有相同的键: 上面是tweeter API的tweet中字段的命令之一(一部分)。我想根据这些命令构建数据框架。 当我尝试直接制作数据框时,每行仅获得一列,并且此列包含整个字典: 当我尝试使用from_dict()创建数据框时,得到相同的结果: 接下来,我尝试了列表理解,但返回了错误: 当我从单行创建数据框时,它几乎

  • 结束时更新更新2结束时更新 我从这里读到:从dataframe列获取列表 熊猫数据框列在拉出时是熊猫系列 然而,我的情况并非如此: 第一部分(建立DataFrame读取json刮擦)因为它包含业务信息,我不能显示完整的代码,但基本上它读取一行数据(存储在系列中),并在DataFrame的末尾追加。 下一部分(检查类型):(请忽略函数的功能) 最后调用函数:(“Raw_Impressions”是一个

  • 问题内容: 我有一个数据框 我有另一个数据框df2 我希望我的最终数据框看起来像: 即从一个数据框映射到另一个创建新列 问题答案: + 假设您的数据框已经在上排序,则第一次排序调用是多余的,在这种情况下,您可以删除它。 / 或者,显式创建映射。如果您以后要使用它,它将起作用。

  • 问题内容: 我试图找到一种数据结构,该数据结构从一系列值中获取特定值并将其映射到键。 例如,我具有以下条件: 从1到2.9,我想将其映射到A。 从4到6,我想将其映射到B。 从6.5到10,我想将其映射到C。 我的值为5,我想将其映射到键。因此,根据上述条件,我应该将其映射到B。 Java中是否有任何人可以推荐给我解决问题的数据结构? 目前,我正在使用只能将值映射到键的哈希表。我试图将值的范围映射

  • 我试图找到一种数据结构,它从一系列值中获取特定值并将其映射到键。 例如,我有以下条件: 从1到2.9,我想把它映射到A. 从4到6,我要把它映射到B. 从6.5到10,我想把它映射到C. 我的值为 5,我想将其映射到一个键。所以基于上述条件,我应该将其映射到B。 Java中有什么数据结构可以推荐给我来解决这个问题吗? 目前我正在使用一个只能将值映射到键的哈希表。我尝试将值的范围映射到哈希表中存在的

  • 问题内容: 我有一个像这样的mongo文件。 我希望能够插入和更新与单个蒙戈命令内不使用条件,然后运行,并根据对象的存在。 这是我要成为选择器的项目。所以如果我用这个更新数组: 我必须使用一个声明 如果我想在数组中插入一个新对象 我必须使用一个声明 我需要一种用于数组项的upsert。 我必须以编程方式执行此操作还是可以通过一个mongo调用来执行此操作? 问题答案: 我不知道在MongoDB 2