无法转置dask.dataframe - 出现Unbound Local Error。

3

我正在尝试转置一个非常大的数据框。由于文件的大小,我使用了Dask,并查找了如何转置Dask数据框。

    import pandas as pd
    import numpy as np
    import dask.dataframe as dd
    genematrix = r"C:\Users\fnafee\Desktop\tobeMerged\GENEMATRIX.csv"
    genematrix_df = dd.read_csv(genematrix)
    new_df = np.transpose(genematrix_df)
    new_df.head()

它返回以下内容。
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [39], in <cell line: 6>()
        4 genematrix = r"C:\Users\fnafee\Desktop\tobeMerged\TSVSMERGED.csv"
        5 genematrix_df = dd.read_csv(genematrix)
  ----> 6 new_df = np.transpose(genematrix_df)
        7 new_df.head()

File <__array_function__ internals>:5, in transpose(*args, **kwargs)

File ~\Anaconda3\lib\site-packages\numpy\core\fromnumeric.py:660, in transpose(a, axes)
      601 @array_function_dispatch(_transpose_dispatcher)
      602 def transpose(a, axes=None):
      603     """
      604     Reverse or permute the axes of an array; returns the modified array.
      605 
     (...)
      658 
      659     """
  --> 660     return _wrapfunc(a, 'transpose', axes)

File ~\Anaconda3\lib\site-packages\numpy\core\fromnumeric.py:54, in _wrapfunc(obj, method, *args, **kwds)
       52 bound = getattr(obj, method, None)
       53 if bound is None:
  ---> 54     return _wrapit(obj, method, *args, **kwds)
       56 try:
       57     return bound(*args, **kwds)

File ~\Anaconda3\lib\site-packages\numpy\core\fromnumeric.py:47, in _wrapit(obj, method, *args, **kwds)
       45     if not isinstance(result, mu.ndarray):
       46         result = asarray(result)
  ---> 47     result = wrap(result)
       48 return result

File ~\Anaconda3\lib\site-packages\dask\dataframe\core.py:4213, in DataFrame.__array_wrap__(self, array, context)
     4210     else:
     4211         index = context[1][0].index
  -> 4213 return pd.DataFrame(array, index=index, columns=self.columns)

UnboundLocalError: local variable 'index' referenced before assignment

问题似乎来自某些我无法控制的内部函数。 我需要更改文件格式还是应该尝试分批处理而不是一个大数据框架?

2个回答

2
这似乎是您在dask中发现的一个不相关的bug。这是一个已知问题(GH#6954),到目前为止,它似乎只会在像您这样使用dask的情况下出现无法工作的情况:)
这个bug只是掩盖了真正的问题,即您不能转置dask.dataframe。这是因为dask.dataframes的一个重要特性是允许行数未知,但列数必须已知。因此,转置数据框将需要计算整个框架。如果这确实是一个矩阵,那么您可能应该使用dask.array或xarray与dask后端(如果需要标记维度)。
例如,给定一个dask.dataframe:
import dask.dataframe as dd, pandas as pd, numpy as np
df = dd.from_pandas(pd.DataFrame({'A': np.arange(100, 200), 'B': np.random.random(size=100)}), npartitions=4)

可以使用 dask.dataframe.to_dask_array 将其转换为 dask.Array,需指定 lengths=True 来定义块的大小:

In [13]: arr = df.to_dask_array(lengths=True)

In [14]: arr
Out[14]: dask.array<values, shape=(100, 2), dtype=float64, chunksize=(25, 2), chunktype=numpy.ndarray>

使用dask.Array.transpose或等效的.T属性,可以在不计算图形的情况下对该数组进行转置:

In [15]: arr.T
Out[15]: dask.array<transpose, shape=(2, 100), dtype=float64, chunksize=(2, 25), chunktype=numpy.ndarray

如果需要使用坐标标签,可以将其包装在 xarray.DataArray 中:
In [22]: import xarray as xr
    ...: da = xr.DataArray(
    ...:     df.to_dask_array(lengths=True),
    ...:     dims=['index', 'columns'],
    ...:     coords=[df.index.compute(), df.columns],
    ...: )

In [23]: da
Out[23]:
<xarray.DataArray 'values-8d50dbfa8ed951a8ffb2ae5d5cd554bb' (index: 100,
                                                             columns: 2)>
dask.array<values, shape=(100, 2), dtype=float64, chunksize=(25, 2), chunktype=numpy.ndarray>
Coordinates:
  * index    (index) int64 0 1 2 3 4 5 6 7 8 9 ... 90 91 92 93 94 95 96 97 98 99
  * columns  (columns) object 'A' 'B'

In [24]: da.T
Out[24]:
<xarray.DataArray 'values-8d50dbfa8ed951a8ffb2ae5d5cd554bb' (columns: 2,
                                                             index: 100)>
dask.array<transpose, shape=(2, 100), dtype=float64, chunksize=(2, 25), chunktype=numpy.ndarray>
Coordinates:
  * index    (index) int64 0 1 2 3 4 5 6 7 8 9 ... 90 91 92 93 94 95 96 97 98 99
  * columns  (columns) object 'A' 'B'

为什么针对数据框架实现转置操作会很困难,即使它已经对数组有效?这两种数据结构有这么大的差别吗? - Soren
是的。分区管理方式非常不同。数组必须具有已知的大小。数据框不需要 - 每个数据框分区的长度可以是未知的,但必须具有已知的列名。此外,分区始终是按行排列的; 在dask中,数据帧分区不能沿列方向进行切块; 而块可以沿着任何维度进行切片。由于这个原因,在数据框转置时会导致无效的数据结构。 - Michael Delgado

0

看起来是缩进问题,因为这个错误提示说变量index在这一行之前没有被赋值。

return pd.DataFrame(array, index=index, columns=self.columns)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接