好…经过大量挖掘,这是怎么回事。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)
,我认为情况并非如此)。呵呵…
看来有逐步淘汰BlockManager的明智计划,因此您的工作量很多。
另请参阅引擎盖下的熊猫,这对我很有帮助。