属性错误:'DataFrame'对象没有'map'属性。

51

我想使用以下代码将 Spark 数据框转换为 add:

from pyspark.mllib.clustering import KMeans
spark_df = sqlContext.createDataFrame(pandas_df)
rdd = spark_df.map(lambda data: Vectors.dense([float(c) for c in data]))
model = KMeans.train(rdd, 2, maxIterations=10, runs=30, initializationMode="random")

详细的错误信息如下:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-11-a19a1763d3ac> in <module>()
      1 from pyspark.mllib.clustering import KMeans
      2 spark_df = sqlContext.createDataFrame(pandas_df)
----> 3 rdd = spark_df.map(lambda data: Vectors.dense([float(c) for c in data]))
      4 model = KMeans.train(rdd, 2, maxIterations=10, runs=30, initializationMode="random")

/home/edamame/spark/spark-2.0.0-bin-hadoop2.6/python/pyspark/sql/dataframe.pyc in __getattr__(self, name)
    842         if name not in self.columns:
    843             raise AttributeError(
--> 844                 "'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
    845         jc = self._jdf.apply(name)
    846         return Column(jc)

AttributeError: 'DataFrame' object has no attribute 'map'

有人知道我在这里做错了什么吗?谢谢!


1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Jeff
@JeffL:我检查了ml,发现输入必须是数据集而不是数据框。所以我们需要进行另一层转换,将数据框转换为数据集才能使用ml? - Edamame
我对区别不再百分之百清楚了,但在Python中,我认为这几乎是无关紧要的。实际上,如果您浏览github代码,在1.6.1中,各种数据框方法位于数据框模块中,而在2.0中,这些相同的方法位于数据集模块中,没有数据框模块。因此,我认为您不会在数据框和数据集之间遇到任何转换问题,至少在Python API中不会。 - Jeff
2个回答

109

你无法对dataframe进行map操作,但是你可以将dataframe转换为RDD并使用spark_df.rdd.map()进行映射。在Spark 2.0之前,spark_df.map会作为spark_df.rdd.map()的别名。从Spark 2.0开始,你必须先显式调用.rdd


2
没错,这是Spark 2.0中数据框架的主要变化之一。 - Mostafa
“RDD” 对象没有属性 “collectAsList”。 - Joe
这具有重大的弊端:“转换为RDD会破坏Dataframe血统,没有谓词下推,没有列修剪,没有SQL计划以及效率较低的PySpark转换。” 更多细节和替代方案请参见我的答案。 - Yosi Dahari
如果可能的话,最好坚持使用DFs,并且几乎所有情况下都应该是可行的。根据您要完成的任务,将有不同的技术来实现它。但是,仍然可能存在将其转换为RDD的用例。 - David

1
你可以使用 df.rdd.map(),因为 DataFrame 没有 mapflatMap,但要注意使用 df.rdd影响

转换为 RDD 会破坏 Dataframe 的血统,没有谓词下推,没有列剪枝,没有 SQL 计划和不那么高效的 PySpark 转换。

相反应该怎么做?

请记住,高级 DataFrame API 配备了许多替代方案。首先,您可以使用 selectselectExpr

另一个例子是使用 explode 而不是 flatMap(它存在于 RDD 中):

df.select($"name",explode($"knownLanguages"))
    .show(false)

结果:

+-------+------+
|name   |col   |
+-------+------+
|James  |Java  |
|James  |Scala |
|Michael|Spark |
|Michael|Java  |
|Michael|null  |
|Robert |CSharp|
|Robert |      |
+-------+------+

您还可以使用withColumnUDF,具体取决于用例,或者DataFrame API中的另一个选项。


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