使用 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
数据,而它期望 int
。 BigData.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 的第一步输入错误的主要内容,如果未能解决你的问题,请参考以下文章
Hive 问题解决 No enum constant org.apache.parquet.hadoop.metadata.CompressionCodecName.LZOP
iceberg org.apache.iceberg.parquet.Parquet parquet file read