将 Pandas 数据帧转换为 Spark 数据帧的 TypeError

Posted

技术标签:

【中文标题】将 Pandas 数据帧转换为 Spark 数据帧的 TypeError【英文标题】:TypeError converting Pandas dataframe to Spark dataframe 【发布时间】:2016-06-24 19:03:47 【问题描述】:

我有一个名为 pdf 的 Pandas 数据框,它只是四列 float64。以下是前五行:

pdf[:5]

      x1         x2        x3          y
0   9.082060  12.837502  6.484107  10.985202
1   9.715981  14.870818  8.026042  12.815644
2  11.303901  21.286343  7.787188  15.786915
3   9.910293  20.533151  6.991775  14.775010
4  12.394907  15.401446  7.101058  13.213897

还有数据类型:

pdf.dtypes

x1    float64
x2    float64
x3    float64
y     float64
dtype: object

但是当我尝试将其转换为 Spark 数据框时:

sdf = sqlContext.createDataFrame(pdf)

TypeErrorTraceback (most recent call last)
<ipython-input-54-a40cb79104b5> in <module>()
      5                     ])
      6 
----> 7 sdf = sqlContext.createDataFrame(pdf)

/usr/lib/spark/python/pyspark/sql/context.py in createDataFrame(self, data, schema, samplingRatio)
    423             rdd, schema = self._createFromRDD(data, schema, samplingRatio)
    424         else:
--> 425             rdd, schema = self._createFromLocal(data, schema)
    426         jrdd = self._jvm.SerDeUtil.toJavaArray(rdd._to_java_object_rdd())
    427         jdf = self._ssql_ctx.applySchemaToPythonRDD(jrdd.rdd(), schema.json())

/usr/lib/spark/python/pyspark/sql/context.py in _createFromLocal(self, data, schema)
    339 
    340         if schema is None or isinstance(schema, (list, tuple)):
--> 341             struct = self._inferSchemaFromList(data)
    342             if isinstance(schema, (list, tuple)):
    343                 for i, name in enumerate(schema):

/usr/lib/spark/python/pyspark/sql/context.py in _inferSchemaFromList(self, data)
    239             warnings.warn("inferring schema from dict is deprecated,"
    240                           "please use pyspark.sql.Row instead")
--> 241         schema = reduce(_merge_type, map(_infer_schema, data))
    242         if _has_nulltype(schema):
    243             raise ValueError("Some of types cannot be determined after inferring")

/usr/lib/spark/python/pyspark/sql/types.py in _infer_schema(row)
    829 
    830     else:
--> 831         raise TypeError("Can not infer schema for type: %s" % type(row))
    832 
    833     fields = [StructField(k, _infer_type(v), True) for k, v in items]

TypeError: Can not infer schema for type: <type 'str'>

如果我尝试指定架构:

schema = StructType([StructField('y', DoubleType()),
                     StructField('x1', DoubleType()),
                     StructField('x2', DoubleType()),
                     StructField('x3', DoubleType())
                    ])
sdf = sqlContext.createDataFrame(pdf, schema)

然后我们得到一个稍微不同的错误:

TypeErrorTraceback (most recent call last)
<ipython-input-55-a7d2b6d09ed3> in <module>()
      5                     ])
      6 
----> 7 sdf = sqlContext.createDataFrame(pdf, schema)

/usr/lib/spark/python/pyspark/sql/context.py in createDataFrame(self, data, schema, samplingRatio)
    423             rdd, schema = self._createFromRDD(data, schema, samplingRatio)
    424         else:
--> 425             rdd, schema = self._createFromLocal(data, schema)
    426         jrdd = self._jvm.SerDeUtil.toJavaArray(rdd._to_java_object_rdd())
    427         jdf = self._ssql_ctx.applySchemaToPythonRDD(jrdd.rdd(), schema.json())

/usr/lib/spark/python/pyspark/sql/context.py in _createFromLocal(self, data, schema)
    348         elif isinstance(schema, StructType):
    349             for row in data:
--> 350                 _verify_type(row, schema)
    351 
    352         else:

/usr/lib/spark/python/pyspark/sql/types.py in _verify_type(obj, dataType)
   1132     if _type is StructType:
   1133         if not isinstance(obj, (tuple, list)):
-> 1134             raise TypeError("StructType can not accept object %r in type %s" % (obj, type(obj)))
   1135     else:
   1136         # subclass of them can not be fromInternald in JVM

TypeError: StructType can not accept object 'x1' in type <type 'str'>

我是否遗漏了一些明显的东西?有没有人成功地从 Pandas 数据框构建火花数据框?这适用于 Python 2.7、Spark v1.6.1 和 Pandas v0.18.1。

【问题讨论】:

嗯...我认为它正在尝试获取您的列标题并将它们也视为数据。尝试取出标题。我的假设基于section 中的最后一个示例。 它肯定似乎与标题有关;如果我将它们更改为整数,则错误将从有关字符串的警告更改为TypeError: Can not infer schema for type: &lt;type 'numpy.int64'&gt;。但我不认为 Pandas 数据框根本就没有标头,可以吗? 它适用于 python 2.7.10spark 1.6.0pandas 0.16.2 可以提供minimal reproducible example吗?特别是很高兴看到您如何创建包含输入数据的 Pandas 数据框(如果相关)。您还可以仔细检查 Pandas 版本:`pd.__version__? @shivsn 所以我回滚到 Pandas 0.16.2,你瞧,它成功了!但后来我升级回 0.18.1 以验证问题......它仍然有效。所以现在我无法复制我自己的问题,我不确定发生了什么变化。也许类似于this issue?如果我再次找到它,我会更新。 【参考方案1】:

我已经成功复制了这个,它似乎只是关闭 ipython 笔记本并重新打开它。当我启动一个只有 Python 2.7 的新集群时,安装了 pip 和 numpy(默认在引导程序中)并使用 pip.main() 安装 Pandas 0.18.1,然后尝试使用 createDataFrame() 将其转换为 Spark 数据帧,它因上述错误而失败。但是当我关闭并停止笔记本然后重新启动它时,它工作正常。

【讨论】:

以上是关于将 Pandas 数据帧转换为 Spark 数据帧的 TypeError的主要内容,如果未能解决你的问题,请参考以下文章

将 spark 数据帧转换为 pandas 数据帧 - ImportError: Pandas >= 0.19.2 must be installed

当我们尝试将巨大的 Pandas 数据帧(40-50 百万行)转换为 Spark 2.0 数据帧时如何提高性能

如何将 Spark 数据帧转换为 Pandas 并返回 Kedro?

在 zeppelin 中将 pandas 数据帧转换为 spark 数据帧

在 Pyspark 中将 Pandas 数据帧转换为 Spark 数据帧的 TypeError

将 pyspark 数据帧转换为 pandas 数据帧