使用 Apache Parquet 的第一步输入错误

Posted

技术标签:

【中文标题】使用 Apache Parquet 的第一步输入错误【英文标题】:Type error on first steps with Apache Parquet 【发布时间】:2018-07-14 16:26:38 【问题描述】:

在第一次尝试 Apache Parquet 文件格式时遇到这种类型的错误相当困惑。 Parquet 不应该支持 Pandas 支持的所有数据类型吗?我错过了什么?

import pandas
import pyarrow
import numpy

data = pandas.read_csv("data/BigData.csv", sep="|", encoding="iso-8859-1")
data_parquet = pyarrow.Table.from_pandas(data)

加注:

---------------------------------------------------------------------------
ArrowInvalid                              Traceback (most recent call last)
<ipython-input-9-90533507bcf2> in <module>()
----> 1 data_parquet = pyarrow.Table.from_pandas(data)

table.pxi in pyarrow.lib.Table.from_pandas()

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pyarrow\pandas_compat.py in dataframe_to_arrays(df, schema, preserve_index, nthreads)
    354             arrays = list(executor.map(convert_column,
    355                                        columns_to_convert,
--> 356                                        convert_types))
    357 
    358     types = [x.type for x in arrays]

~\AppData\Local\Continuum\anaconda3\lib\concurrent\futures\_base.py in result_iterator()
    584                     # Careful not to keep a reference to the popped future
    585                     if timeout is None:
--> 586                         yield fs.pop().result()
    587                     else:
    588                         yield fs.pop().result(end_time - time.time())

~\AppData\Local\Continuum\anaconda3\lib\concurrent\futures\_base.py in result(self, timeout)
    423                 raise CancelledError()
    424             elif self._state == FINISHED:
--> 425                 return self.__get_result()
    426 
    427             self._condition.wait(timeout)

~\AppData\Local\Continuum\anaconda3\lib\concurrent\futures\_base.py in __get_result(self)
    382     def __get_result(self):
    383         if self._exception:
--> 384             raise self._exception
    385         else:
    386             return self._result

~\AppData\Local\Continuum\anaconda3\lib\concurrent\futures\thread.py in run(self)
     54 
     55         try:
---> 56             result = self.fn(*self.args, **self.kwargs)
     57         except BaseException as exc:
     58             self.future.set_exception(exc)

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pyarrow\pandas_compat.py in convert_column(col, ty)
    343 
    344     def convert_column(col, ty):
--> 345         return pa.array(col, from_pandas=True, type=ty)
    346 
    347     if nthreads == 1:

array.pxi in pyarrow.lib.array()

array.pxi in pyarrow.lib._ndarray_to_array()

error.pxi in pyarrow.lib.check_status()

ArrowInvalid: Error converting from Python objects to Int64: Got Python object of type str but can only handle these types: integer

data.dtypes 是:

0      object
1      object
2      object
3      object
4      object
5     float64
6     float64
7      object
8      object
9      object
10     object
11     object
12     object
13    float64
14     object
15    float64
16     object
17    float64
...

【问题讨论】:

回溯的最后一行表明 Arrow 正在获取 str 数据,而它期望 intBigData.csv 的前几行是什么? dtype="16": numpy.object 告诉 pandas not 只解释第 16 列的 dtype,而不解释其他列。如果你删除它然后再试一次呢? 删除后,错误依旧。 嗯,好的。您能否将BigData.csv 的前几行添加到问题中? 不确定我能不能,因为数据集是机密的。我有一个可能的罪魁祸首:我知道一列的一行中有一个字符串,否则全是数字 - 这会导致错误吗? 在我有限的测试中,我无法使用混合类型的列重现您的确切错误消息。抱歉,我无法提供更多帮助! 【参考方案1】:

在 Apache Arrow 中,表列的数据类型必须是同质的。 pandas 支持 Python 对象列,其中值可以是不同的类型。因此,在写入 Parquet 格式之前,您需要进行一些数据清理。

我们已经在 Arrow-Python 绑定中处理了一些基本情况(例如列中的字节和 unicode),但我们不会冒险猜测如何处理不良数据。我打开了 JIRA https://issues.apache.org/jira/browse/ARROW-2098 关于添加一个选项以在这种情况下将意外值强制为 null,这可能会在未来有所帮助。

【讨论】:

【参考方案2】:

遇到了同样的问题,我花了一段时间才想办法找到有问题的专栏。这是我找到混合类型列的方法 - 尽管我知道必须有更有效的方法。

异常发生前打印的最后一列是混合类型列。

# method1: try saving the parquet file by removing 1 column at a time to 
# isolate the mixed type column.
cat_cols = df.select_dtypes('object').columns
for col in cat_cols:
    drop = set(cat_cols) - set([col])
    print(col)
    df.drop(drop, axis=1).reset_index(drop=True).to_parquet("c:/temp/df.pq")

另一种尝试 - 根据唯一值列出列和每种类型。

# method2: list all columns and the types within
def col_types(col):
    types = set([type(x) for x in col.unique()])
    return types

df.select_dtypes("object").apply(col_types, axis=0)

【讨论】:

【参考方案3】:

我遇到过类似的情况,如果可能的话,您可以先将所有columns 转换为所需的字段数据类型,然后尝试转换为镶木地板。示例:-

import pandas as pd
column_list = df.columns
for col in column_list:
    df[col] = df[col].astype(str)

df.to_parquet('df.parquet.gzip', compression='gzip')

【讨论】:

以上是关于使用 Apache Parquet 的第一步输入错误的主要内容,如果未能解决你的问题,请参考以下文章

parquet常用操作

扫盲贴001---django框架的第一步

ubuntu安装中文拼音输入法,装系统的第一步

Hive 问题解决 No enum constant org.apache.parquet.hadoop.metadata.CompressionCodecName.LZOP

SQL注入之报错注入

iceberg org.apache.iceberg.parquet.Parquet parquet file read