6

我想在不复制数据的情况下连接两个熊猫 DataFrame。也就是说,我希望连接的 DataFrame 是两个原始 DataFrame 中数据的视图。我尝试使用 concat() 并没有奏效。此代码块显示更改基础数据会影响连接的两个 DataFrame,但不会影响连接的 DataFrame:

arr = np.random.randn(12).reshape(6, 2)
df = pd.DataFrame(arr, columns = ('VALE5', 'PETR4'), index = dates)
arr2 = np.random.randn(12).reshape(6, 2)
df2 = pd.DataFrame(arr, columns = ('AMBV3', 'BBDC4'), index = dates)
df_concat = pd.concat(dict(A = df, B = df2),axis=1)
pp(df)
pp(df_concat)
arr[0, 0] = 9999999.99
pp(df)
pp(df_concat)

这是最后五行的输出。将新值分配给 arr[0, 0] 后,df 发生了变化;df_concat 不受影响。

In [56]: pp(df)
           VALE5     PETR4
2013-01-01 -0.557180  0.170073
2013-01-02 -0.975797  0.763136
2013-01-03 -0.913254  1.042521
2013-01-04 -1.973013 -2.069460
2013-01-05 -1.259005  1.448442
2013-01-06 -0.323640  0.024857

In [57]: pp(df_concat)
               A                   B          
           VALE5     PETR4     AMBV3     BBDC4
2013-01-01 -0.557180  0.170073 -0.557180  0.170073
2013-01-02 -0.975797  0.763136 -0.975797  0.763136
2013-01-03 -0.913254  1.042521 -0.913254  1.042521
2013-01-04 -1.973013 -2.069460 -1.973013 -2.069460
2013-01-05 -1.259005  1.448442 -1.259005  1.448442
2013-01-06 -0.323640  0.024857 -0.323640  0.024857

In [58]: arr[0, 0] = 9999999.99

In [59]: pp(df)
                 VALE5     PETR4
2013-01-01  9999999.990000  0.170073
2013-01-02       -0.975797  0.763136
2013-01-03       -0.913254  1.042521
2013-01-04       -1.973013 -2.069460
2013-01-05       -1.259005  1.448442
2013-01-06       -0.323640  0.024857

In [60]: pp(df_concat)
               A                   B          
           VALE5     PETR4     AMBV3     BBDC4
2013-01-01 -0.557180  0.170073 -0.557180  0.170073
2013-01-02 -0.975797  0.763136 -0.975797  0.763136
2013-01-03 -0.913254  1.042521 -0.913254  1.042521
2013-01-04 -1.973013 -2.069460 -1.973013 -2.069460
2013-01-05 -1.259005  1.448442 -1.259005  1.448442
2013-01-06 -0.323640  0.024857 -0.323640  0.024857

我猜这意味着 concat() 创建了数据的副本。有没有办法避免复制?(我想尽量减少内存使用)。

此外,是否有一种快速的方法来检查两个 DataFrame 是否链接到相同的基础数据?(无需经历更改数据和检查每个 DataFrame 是否已更改的麻烦)

谢谢您的帮助。

FS

4

1 回答 1

3

你不能(至少很容易)。当您调用时concat,最终np.concatenate会被调用。

请参阅此答案,解释为什么不复制就无法连接数组。缺点是数组不能保证在内存中是连续的。

这是一个简单的例子

a = rand(2, 10)
x, y = a
z = vstack((x, y))
print 'x.base is a and y.base is a ==', x.base is a and y.base is a
print 'x.base is z or y.base is z ==', x.base is z or y.base is z

输出:

x.base is a and y.base is a == True
x.base is z or y.base is z == False

即使xy共享相同base,即aconcatenate(因此vstack)不能假设他们这样做,因为人们经常想要连接任意跨步数组。

您可以轻松地生成两个具有不同步幅的数组,共享相同的内存,如下所示:

a = arange(10)
b = a[::2]
print a.strides
print b.strides

输出:

(8,)
(16,)

这就是为什么会发生以下情况:

In [214]: a = arange(10)

In [215]: a[::2].view(int16)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-215-0366fadb1128> in <module>()
----> 1 a[::2].view(int16)

ValueError: new type not compatible with array.

In [216]: a[::2].copy().view(int16)
Out[216]: array([0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 8, 0, 0, 0], dtype=int16)

编辑:使用pd.merge(df1, df2, copy=False)(或df1.merge(df2, copy=False))何时df1.dtype != df2.dtype不会复制。否则,将制作一份副本。

于 2013-08-18T05:41:56.883 回答