在将pandas数据帧转换为cudf数据帧时,缓冲区大小必须可被元素大小整除

时间:2020-04-21 12:31:10

标签: python pandas numpy cudf

我有一个数据框,其中的一列是用引号(即字符串对象)编码的逗号分隔值。 例如:

  df['a']
'1,2,3,4,5'
'2,3,4,5,6'

我能够将字符串格式的值列表转换为NumPy数组,并能够成功执行操作。

def func(x):
    return something

for t_df in pd.read_csv("testset.csv",chunksize=2000):
    t_df['predicted'] = t_df['prev'].parallel_apply(lambda x : arima(ast.literal_eval(x),1))

直到现在我都没有任何问题。但是 func 运行预测模型非常耗时,数据帧大小为200万条记录。

因此,我尝试使用python中的cudf软件包来利用数据帧等熊猫上的GPU功能。这里出现了问题

for t_df in pd.read_csv("testset.csv",chunksize=2):
    t_df['prev'] = t_df['prev'].apply(lambda x : np.array(ast.literal_eval(x)))
    t_df = cudf.DataFrame.from_pandas(t_df)

当我执行相同的操作时,它失败了,并出现错误,该错误基本上无法将类似字符串的对象转换为NumPy数组。 错误如下

> ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-19-e7866d751352> in <module>
     12     t_df['prev'] = t_df['prev'].apply(lambda x : np.array(ast.literal_eval(x)))
     13     st = time.time()
---> 14     t_df = cudf.DataFrame.from_pandas(t_df)
     15     t_df['predicted'] = 10
     16     res.append(t_df)

/opt/conda/lib/python3.7/site-packages/cudf/core/dataframe.py in from_pandas(cls, dataframe, nan_as_null)
   3109             # columns for a single key
   3110             if len(vals.shape) == 1:
-> 3111                 df[i] = Series(vals, nan_as_null=nan_as_null)
   3112             else:
   3113                 vals = vals.T

/opt/conda/lib/python3.7/site-packages/cudf/core/series.py in __init__(self, data, index, name, nan_as_null, dtype)
    128 
    129         if not isinstance(data, column.ColumnBase):
--> 130             data = column.as_column(data, nan_as_null=nan_as_null, dtype=dtype)
    131 
    132         if index is not None and not isinstance(index, Index):

/opt/conda/lib/python3.7/site-packages/cudf/core/column/column.py in as_column(arbitrary, nan_as_null, dtype, length)
   1353         elif arb_dtype.kind in ("O", "U"):
   1354             data = as_column(
-> 1355                 pa.Array.from_pandas(arbitrary), dtype=arbitrary.dtype
   1356             )
   1357         else:

/opt/conda/lib/python3.7/site-packages/cudf/core/column/column.py in as_column(arbitrary, nan_as_null, dtype, length)
   1265                 mask=pamask,
   1266                 size=pa_size,
-> 1267                 offset=pa_offset,
   1268             )
   1269 

/opt/conda/lib/python3.7/site-packages/cudf/core/column/numerical.py in __init__(self, data, dtype, mask, size, offset)
     30         dtype = np.dtype(dtype)
     31         if data.size % dtype.itemsize:
---> 32             raise ValueError("Buffer size must be divisible by element size")
     33         if size is None:
     34             size = data.size // dtype.itemsize

ValueError: Buffer size must be divisible by element size

可能是什么解决方案?

1 个答案:

答案 0 :(得分:0)

As in your other question, I believe that you're trying to force cudf into doing something in a way that you really shouldn't.尽管RAPIDS致力于API的熟悉性,但似乎:

  1. 您当前没有使用cudf或cuml最佳做法。尽管您的意图可行,但是您并没有使用最佳实践来实现您的目标,而我们确实为此提供了资源。
  2. 尽管RAPIDS可以读取csv中的内容,但是您的预处理尝试将np.array推送到单个列中,而cudf无法读取该格式(这给您带来了错误)。您需要将输出更改为RAPIDS可以读取的内容,例如为该数组中的每个元素创建一列(下面的代码)。这可能是您遇到的熊猫和RAPIDS之间的功能差异,我们建议您提出功能要求。

如果您还没有,我建议您使用go through some of our docsnotebook examples in cuml and cudf on githubWe have an arima example notebook that runs on GPU。这些是快速阅读的书,确实可以助您一臂之力。 cudf可以使用.str本机处理字符串,但是我们的apply尚不适用于字符串。如果您的GPU内存太小而无法容纳所有数据,请使用dask-cudf。

这里最棘手的部分是读取数据集,该数据集的CSV中包含逗号分隔的字符串元素。您希望每个元素都沿着行放在自己的列中,而不是数组。 RAPIDS applys在字符串上还不能很好地工作,但是您要完成的工作与下面的示例代码非常相似。可悲的是,RAPIDS可能比Pandas花费更长的时间。但是,该代码对cudf和pandas均适用,并且其输出在整个RAPIDS生态系统中更有用。现在,您已将向量划分为列,然后使用cuml的ARIMA(在上方链接)查看将您带到何处。

import cudf
df = cudf.read_csv('testset.csv') 
vecnum_cols = ['a'] 
df_vecnum = cudf.DataFrame(index=df.index)

if len(vecnum_cols) >0:
    for vec in vecnum_cols:
        v = df[vec].str.split(",", expand = True).reset_index(drop=True)
        v.columns  = [ vec + '_' + str(i) for i in range(v.shape[1])]
        #print(len(v.columns))
        df_vecnum = df_vecnum.join(v) 
print(df_vecnum.head())

希望这对您有所帮助。我不能保证会把您带到您想去的地方,但是根据我上面看到的,它应该使您朝着正确的方向前进。

相关问题