未复制的熊猫数据框

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框架。