在Apache Spark中将Dataframe的列值提取为List
我想将一个数据框的string列转换为列表。 我可以从Dataframe
APIfind的是RDD,所以我试着先将它转换回RDD,然后将toArray
函数应用于RDD。 在这种情况下,长度和SQL工作得很好。 不过,我从RDD获得的结果在每个元素周围都有方括号[A00001]
。 我想知道是否有一个适当的方式将列转换为列表或删除方括号的方法。
任何build议,将不胜感激。 谢谢!
这应该返回包含单个列表的集合:
dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()
如果没有映射,只需获取Row对象,其中包含数据库中的每一列。
请记住,这可能会给你一个任何types的列表。 如果要指定结果types,可以在r => r(0).asInstanceOf[YOUR_TYPE]
映射中使用r => r(0).asInstanceOf[YOUR_TYPE]
PS由于自动转换,您可以跳过.rdd
部分。
Spark 2.x和Scala 2.11
我想到了3种可能的方式将特定列的值转换为List
所有方法的通用代码片段
import org.apache.spark.sql.SparkSession val spark = SparkSession.builder.getOrCreate import spark.implicits._ // for .toDf() method val df = Seq( ("first", 2.0), ("test", 1.5), ("choose", 8.0) ).toDF("id", "val")
方法1
df.select("id").collect().map(_(0)).toList // res9: List[Any] = List(one, two, three)
现在会发生什么? 我们正在收集数据给驱动程序collect()
并从每个logging中选取元素0。
这不是一个很好的做法,让我们用下一个方法来改进。
方法2
df.select("id").rdd.map(r => r(0)).collect.toList //res10: List[Any] = List(one, two, three)
怎么样更好? 我们在工作人员之间分配了地图转换负载,而不是单个Driver。
我知道rdd.map(r => r(0))
似乎并不优雅。 所以,我们用下一个方法来解决它。
方法3
df.select("id").map(r => r.getString(0)).collect.toList //res11: List[String] = List(one, two, three)
这里我们不是把DataFrame转换成RDD。 看看map
,由于DataFrame中的编码器问题,它不会接受r => r(0)
(或_(0)
)作为以前的方法。 所以最后使用r => r.getString(0)
,它将在下一个版本的Spark中解决。
结论
所有的选项给出相同的输出,但2和3是有效的,最后第三个是有效和优雅(我想)。
Databricks笔记本链接将从2017/05/20起提供至6个月
我知道给出的答案是针对Scala的,所以我只是提供一小段Python代码,以防PySpark用户好奇。 语法与给定的答案类似,但要正确地popup列表,我实际上必须在映射函数中第二次引用列名,而且我不需要select语句。
即一个DataFrame,包含一个名为“Raw”的列
要将“Raw”中的每一行值合并为一个列表,其中每个条目是来自“Raw”的行值,我只需使用:
MyDataFrame.rdd.map(lambda x: x.Raw).collect()
在Scala和Spark 2+中,试试这个(假设你的列名是“s”): df.select('s).as[String].collect
我没有足够的代表来回复上面的post,但是它会写出错误的方式^^。 我不得不改变它到以下来得到它的工作(基本上去除对每个X的调用Raw):
MyDataFrame.rdd.map(lambda x: x).collect()
它似乎返回一个Row对象的列表(在这里使用我的例子):
>>> df.select('name').rdd.map(lambda r: r).collect() [Row(name=u'Yin'), Row(name=u'Michael')]