我似乎可以通过创建一个mmap的ndarray并用它初始化Series来memmap python系列的底层数据。
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
由只读内存Mapndarray支持。我可以对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),... result in copies.
我有几千个大的列作为数据文件,我一次只需要其中的几个。我希望我能把它们的mmap表示放在一个DataFrame中,如上所述。这可能吗?
Pandas的文档让我们很难猜出它的内部是什么--尽管它确实说了一个DataFrame "Can be thought of as a dict-like container for Series objects."。
我不想用HD 5来解决这个问题。
2条答案
按热度按时间tct7dpnv1#
好吧......经过大量的挖掘,这就是正在发生的事情。
当copy=False参数被提供给构造函数时,pandas会为一个系列维护对supplies数组的引用:
对于DataFrame则不适用:
Pandas的
DataFrame
使用BlockManager
类在内部组织数据。与文档相反,DataFrame
不是一个系列的集合,而是一个 * 类似dtyped矩阵的集合 *。BlockManger
将所有float列组合在一起,所有int列组合在一起,等等...,它们的内存(据我所知)保持在一起。只有在提供了一个
ndarray
矩阵(单一类型)的情况下,它才可以不复制内存。注意,BlockManager
(理论上)也支持在其构造中不复制混合类型的数据,因为它可能不需要将此输入复制到相同类型的分块中。然而,DataFrame
构造函数只有在数据参数为单一矩阵的情况下才不进行复制。简而言之,如果你有混合类型或多个数组作为构造函数的输入,或者提供一个带有单个数组的dict,你在Pandas中就不走运了,
DataFrame
的默认BlockManager
会复制你的数据。在任何情况下,解决这个问题的一种方法是强制
BlockManager
不按类型合并,而是将每一列作为一个单独的“块”。如果指定了
copy=False
,则DataFrame
或BlockManger
具有consolidate=False
(或假设此行为)会更好。测试:
我觉得
BlockManager
要求将类似类型的数据保存在一起是否真的有实际的好处有点疑问--Pandas中的大多数操作都是按标签行或按列进行的--这是因为DataFrame
是一种异构列的结构,通常只通过它们的索引进行关联。尽管可行,但它们为每个“块”保留一个索引,如果索引将偏移量保留在块中,则会获得好处(如果是这种情况,那么它们应该按sizeof(dtype)
分组,我不认为是这种情况)。呵呵……
有一些关于provide a non-copying constructor的PR的讨论,但被放弃了。
看起来有合理的plans to phase out
BlockManager
,所以你的里程可能会有所不同。Pandas under the hood,这对我很有帮助。
46scxncf2#
如果您更改DataFrame构造函数以添加参数copy=False,则将获得所需的行为。https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html
编辑:此外,您希望使用底层ndarray(而不是pandas系列)。