【问题标题】:Is there a non-copying constructor for a pandas DataFramepandas DataFrame 是否有非复制构造函数
【发布时间】:2014-06-19 13:41:22
【问题描述】:

转自https://groups.google.com/forum/#!topic/pydata/5mhuatNAl5g

似乎在从结构化数组创建 DataFrame 时复制了数据? 如果数据是 numpy 数组的字典,我会得到类似的结果。

是否可以在不进行任何复制或检查的情况下从结构化数组或类似数组中创建 DataFrame?

In [44]: sarray = randn(1e7,10).view([(name, float) for name in 'abcdefghij']).squeeze()

In [45]: for N in [10,100,1000,10000,100000,1000000,10000000]:
    ...:     s = sarray[:N]
    ...:     %timeit z = pd.DataFrame(s)
    ...: 
1000 loops, best of 3: 830 µs per loop
1000 loops, best of 3: 834 µs per loop
1000 loops, best of 3: 872 µs per loop
1000 loops, best of 3: 1.33 ms per loop
100 loops, best of 3: 15.4 ms per loop
10 loops, best of 3: 161 ms per loop
1 loops, best of 3: 1.45 s per loop 

谢谢, 戴夫

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    Panda 的 DataFrame 使用 BlockManager 将类似类型的数据合并到单个内存块中。它将这种合并为一个导致复制的块。如果初始化如下:

    pd.DataFrame(npmatrix, copy=False)
    

    那么DataFrame不会复制数据,而是引用它。

    但是,有时您可能会使用多个数组,BlockManager 会尝试将数据合并到一个块中。在这种情况下,我认为您唯一的选择是monkey patch the BlockManager to not consolidate the data

    我同意@DaveHirschfeld,这可以作为consolidate=False 参数提供给BlockManager。熊猫会更好。

    【讨论】:

      【解决方案2】:

      这将根据定义将 dtype 强制为单个 dtype(例如,在这种情况下为 float64)。没办法。这是原始数组的视图。请注意,这仅有助于构建。大多数操作都倾向于制作和返回副本。

      In [44]: s = sarray[:1000000]
      

      原始方法

      In [45]: %timeit DataFrame(s)
      10 loops, best of 3: 107 ms per loop
      

      强制转换为 ndarray。传入copy=False(这不会影响结构化数组,只会影响普通的单个 dtyped ndarray)。

      In [47]: %timeit DataFrame(s.view(np.float64).reshape(-1,len(s.dtype.names)),columns=s.dtype.names,copy=False)
      100 loops, best of 3: 3.3 ms per loop
      
      In [48]: result = DataFrame(s.view(np.float64).reshape(-1,len(s.dtype.names)),columns=s.dtype.names,copy=False)
      
      In [49]: result2 = DataFrame(s)
      
      In [50]: result.equals(result2)
      Out[50]: True
      

      请注意,DataFrame.from_dictDataFrame.from_records 都会复制此内容。 Pandas 将 like-dtyped ndarray 保留为 single ndarray。做一个np.concatenate 来聚合是很昂贵的,这是在幕后完成的。使用视图可以避免这个问题。

      如果传递的 dtypes 都相同,我想这可能是结构化数组的默认值。但是你必须首先问为什么要使用结构化数组。 (显然是为了获得名称访问权..但这是他们的另一个原因吗?)

      【讨论】:

      • 我正在使用 Continuum 的 IOPro 进行大型数据库查询。它可以通过直接构造结构化数组而不经过python类型来显着减少使用的内存并加快查询速度。不幸的是,从数组创建 DataFrame 会复制它,从而失去一些性能优势。
      • 不幸的是,查询返回的数据不是单一的同质类型,因此视图技巧不起作用。如果您传递异构 numpy 数组的列表或字典,是否有任何理由必须复制它们?它不能只引用每个吗?
      • 正如我上面解释的那样,dtypes 被合并到单个 ndarrays 中,所以它们必须被连接起来(这是所有时间都花在的地方)。如果需要,您可以简单地将它们保留为 Series 的字典以不复制。但是你必须手动对齐它们,操作变得很棘手。最好这样做一次,然后将它们写为 HDF5 文件;他们已经被 dtypes 阻止了(阅读时)。
      • 拥有一个consolidate=False 是否可行,以便它只引用底层数组而不是分配内存和复制数据?然后可以将复制成本推迟到您需要执行需要复制的操作时。
      • 尝试燃烧。这将是一个不平凡的重大变化。它可以完成(任何事情都可以完成)。这当然是可能的,例如,sparse 类型是不可合并的,Categoricals 也是如此。但需要某人付出巨大的努力。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2023-03-20
      • 1970-01-01
      • 2016-01-17
      • 1970-01-01
      • 2010-10-01
      • 2014-09-27
      相关资源
      最近更新 更多