Pandas dataframe without copy
如何避免在创建Pandas DataFrame时复制提供的字典?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | >>> a = np.arange(10) >>> b = np.arange(10.0) >>> df1 = pd.DataFrame(a) >>> a[0] = 100 >>> df1 0 0 100 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 >>> d = {'a':a, 'b':b} >>> df2 = pd.DataFrame(d) >>> a[1] = 200 >>> d {'a': array([100, 200, 2, 3, 4, 5, 6, 7, 8, 9]), 'b': array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])} >>> df2 a b 0 100 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9 |
如果我仅从a创建数据帧,则对a的更改将反映在df中(反之亦然)。
提供字典时,有什么方法可以使这项工作正常进行吗?
可以在不复制数据的情况下初始化数据帧。要了解其方式,您需要了解BlockManager,它是DataFrame使用的基础数据结构。它试图将相同dtype的数据分组在一起,并将其内存保存在一个块中-正如文档所说,它不用作列的列。如果数据已经作为一个单独的块提供,例如,您从矩阵进行初始化:
1 2 3 4 | a = np.zeros((100,20)) a.flags['WRITEABLE'] = False df = pd.DataFrame(a, copy=False) assert_read_only(df[df.columns[0]].iloc) |
...然后,DataFrame通常只会引用ndarray。
但是,如果您从多个数组开始或具有异构类型,则此方法将无效。
在这种情况下,您可以猴子修补BlockManager,以强制其不合并相同类型的数据列。
但是,如果您使用非numpy数组初始化数据框,那么pandas将立即将其复制。
无法"共享"字典并根据字典更改来更新框架。复制参数与字典无关,数据始终会被复制,因为它已转换为ndarray。
但是,有一种方法可以以有限的方式获得这种动态行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | In [9]: arr = np.array(np.random.rand(5,2)) In [10]: df = DataFrame(arr) In [11]: arr[0,0] = 0 In [12]: df Out[12]: 0 1 0 0.000000 0.192056 1 0.847185 0.609028 2 0.833997 0.422521 3 0.937638 0.711856 4 0.047569 0.033282 |
因此,在构造时传递的ndarray将成为基础numpy数组的视图。根据您在DataFrame上的操作方式,您可以触发一个副本(例如,如果您指定说一个新列,或更改dtype列)。这也仅适用于单个dtyped框架。