Apache spark pyspark:将数据帧的行合并到DenseVector中
我有一个带有两列的Apache spark pyspark:将数据帧的行合并到DenseVector中,apache-spark,pyspark,spark-dataframe,pyspark-sql,Apache Spark,Pyspark,Spark Dataframe,Pyspark Sql,我有一个带有两列的DataFrame: df=sqlContext.createDataFrame([ (1,'a'),(2,'a'), (3"b",(4"b"),, (5,'c'),(6,'c'), (7,'d'),(8,'d'), ],schema=['value','name']) 编辑2017/01/13: 我从基于实体属性值模型的SQL表派生出这个数据帧。因此,每一行都有一个额外的第三个实体列“id” 我想将其转换为ml包的分类器所需的“features”DataFrame。对于单个
DataFrame
:
df=sqlContext.createDataFrame([
(1,'a'),(2,'a'),
(3"b",(4"b"),,
(5,'c'),(6,'c'),
(7,'d'),(8,'d'),
],schema=['value','name'])
编辑2017/01/13:
我从基于实体属性值模型的SQL表派生出这个数据帧。因此,每一行都有一个额外的第三个实体列“id”
我想将其转换为ml
包的分类器所需的“features”DataFrame
。对于单个列,这可以使用矢量汇编程序实现:
来自pyspark.ml.feature导入向量汇编程序
assembler=VectorAssembler(inputCols=['value'],outputCol=“features”)
所选特征=汇编程序.transform(df).select('features')
所选功能。收集()
[世界其他地区(特征=DenseVector([1.0])),
行(特征=DenseVector([2.0]),
行(特征=DenseVector([3.0]),
行(特征=DenseVector([4.0]),
行(特征=DenseVector([5.0]),
行(特征=DenseVector([6.0]),
行(特征=DenseVector([7.0]),
行(特征=DenseVector([8.0]))]
我想要的是:
[行(功能=DenseVector([1.0,2.0])),
行(特征=DenseVector([3.0,4.0]),
行(特征=DenseVector([5.0,6.0]),
行(特征=DenseVector([7.0,8.0]))]
根据列名称
的值,将列值
的值组合成一个DenseVector
最有效的方法是什么
例如,我正在考虑一个自定义聚合函数,它将与groupby
一起工作:
df.groupby('name').vector_agg().collect()
与PostgreSQL函数类似:
从表中选择数组_agg(df.value)作为df
按df.name分组;
从您的数据结构中,您只需使用相同的表和过滤器对值相同(或倒置)的行执行连接
df=sqlContext.createDataFrame([
(1,'a'),(2,'a'),
(3"b",(4"b"),,
(5,'c'),(6,'c'),
(7,'d'),(8,'d'),
],schema=['value','name'])
xf=df.select(df[“name”].别名(“nam”)、df[“value”].别名(“val”))
pf=df.join(xf,df[“name”]==xf[“nam”],“inner”)。其中(xf[“val”]
我认为你的问题定义不清楚,因为对于一个固定的名称
没有办法知道哪个值
属于哪个列。ml
包中的分类器都要求在训练样本之间一致地使用每个列。在您的示例中,列恰好是按所需的顺序提供的,但实际上您不能依赖于此
如果您能给出功能索引并从以下内容开始,您的问题就可以得到解决:
df = sc.sql.createDataFrame([
('a', ('f1', 1)), ('a', ('f2', 2)),
('b', ('f1', 3)), ('b', ('f2', 4)),
('c', ('f1', 5)), ('c', ('f2', 6)),
('d', ('f1', 7)), ('d', ('f2', 8)),
], schema=['name', 'feature'])
首先,按名称
分组,并将您的功能聚合为一个列表:
import pyspark.sql.functions as F
df.groupBy('name')\
.agg(F.collect_list('feature'))\
.show()
输出:
+----+---------------------+
|name|collect_list(feature)|
+----+---------------------+
| d| [[f1,7], [f2,8]]|
| c| [[f1,5], [f2,6]]|
| b| [[f1,3], [f2,4]]|
| a| [[f1,1], [f2,2]]|
+----+---------------------+
[Row(features=DenseVector([7.0, 8.0])),
Row(features=DenseVector([5.0, 6.0])),
Row(features=DenseVector([3.0, 4.0])),
Row(features=DenseVector([1.0, 2.0]))]
接下来,使用with column
中的udf将此数组转换为DenseVector。总而言之:
from pyspark.ml.linalg import Vectors, VectorUDT
import pyspark.sql.functions as F
list_to_dense = F.udf(lambda l: Vectors.dense([v for (k,v) in sorted(l)]), VectorUDT())
df.groupBy('name')\
.agg(F.collect_list('features'))\
.withColumn('features', list_to_dense('collect_list(features)'))\
.select('features')\
.collect()
输出:
+----+---------------------+
|name|collect_list(feature)|
+----+---------------------+
| d| [[f1,7], [f2,8]]|
| c| [[f1,5], [f2,6]]|
| b| [[f1,3], [f2,4]]|
| a| [[f1,1], [f2,2]]|
+----+---------------------+
[Row(features=DenseVector([7.0, 8.0])),
Row(features=DenseVector([5.0, 6.0])),
Row(features=DenseVector([3.0, 4.0])),
Row(features=DenseVector([1.0, 2.0]))]
对于我提供的非常简单的示例,这很好,但我正在寻找一种更通用的方法。我改进了我的问题,你说得对!问题与处理基于实体-属性-值模型的SQL表有关。因此将有第三个实体列。我会相应地更新问题。collect\u list
是我要找的