【问题标题】:Pandas dataframe without copy没有副本的熊猫数据框
【发布时间】:2013-04-30 19:38:51
【问题描述】:

如何避免复制创建 Pandas DataFrame 时提供的字典?

>>> 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 中(反之亦然)。

在提供字典时有什么方法可以使这项工作发挥作用吗?

【问题讨论】:

  • 完全没有意识到它会这样做。

标签: pandas


【解决方案1】:

没有办法“共享”一个字典并根据字典的变化更新框架。 copy 参数与 dict 无关,数据总是被复制,因为它被转换为 ndarray。

但是,有一种方法可以以有限的方式获得这种类型的动态行为。

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

【讨论】:

    【解决方案2】:

    可以在不复制数据的情况下初始化数据框。要了解如何,您需要了解 BlockManager,它是 DataFrame 使用的底层数据结构。它试图将相同 dtype 的数据组合在一起,并将它们的内存保存在一个块中——它 像文档中所说的那样作为列的列。 如果数据已作为单个块提供,例如您从矩阵初始化:

            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。

    但是,如果您从多个数组开始或具有异构类型,这将不起作用。 在这种情况下,您可以monkey patch the BlockManager 强制它不合并相同类型的数据列。

    但是,如果您使用非 numpy 数组初始化数据框,那么 pandas 会立即复制它。

    【讨论】:

      猜你喜欢
      • 2019-04-17
      • 2013-07-31
      • 1970-01-01
      • 2015-02-06
      • 2016-12-14
      • 2018-11-06
      • 2023-01-26
      • 2015-04-19
      相关资源
      最近更新 更多