我正在应用频繁的模式分析,需要一些输入类型的帮助。
首先,我使用stringindexer将我的分类变量转换为数字。
之后,我为每个分类值创建一个唯一的数字,如下所示:
add_100=udf(lambda x:x+100,returnType=FloatType())
add_1000=udf(lambda x:x+1000,returnType=FloatType())
df = df.select('cat_var_1', add_1000('cat_var_2').alias('cat_var_2_final'), add_10000('cat_var_3').alias('cat_var_3_final'))
我的下一步是创建一个具有以下功能的矢量:
featuresCreator = ft.VectorAssembler(inputCols=[col for col in features], outputCol='features')
df=featuresCreator.transform(df)
最后,我尝试适合我的模型:
from pyspark.ml.fpm import FPGrowth
fpGrowth = FPGrowth(itemsCol="features", minSupport=0.5, minConfidence=0.6)
model = fpGrowth.fit(df)
并收到此错误:
u'requirement failed:输入列必须是ArrayType,但得到了 org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7。
所以,问题是,如何将矢量转换为数组?或者,我还有其他方法可以解决这个问题吗?
答案 0 :(得分:2)
FPGrowth采用数组而不是Vector。由于VectorAssembler
将为您提供矢量作为输出,因此可能的简单解决方案是使用UDF
将该输出转换为数组。
to_array = udf(lambda x: x.toArray(), ArrayType(DoubleType()))
df = df.withColumn('features', to_array('features'))
更好的解决方案是一次完成所有操作,即根本不使用VectorAssembler
。这样做的好处是根本不需要UDF
,因此速度更快。这使用了pyspark内置的array
函数。
from pyspark.sql import functions as F
df2 = df.withColumn('features', F.array('cat_var_1', 'cat_var_2', 'cat_var_3'))
答案 1 :(得分:2)
我认为,您不需要udf来创建唯一编号。或者您可以直接使用withColumn,
df = df.withColumn('cat_var_2_final',df['cat_var_2']+100).withColumn('cat_var_3_final',df['cat_var_3']+1000)
而且,如果你只为FPGrowth模型提供这些数据,我们也可以跳过vectorassembler并使用udf直接创建数组特征,
udf1 = udf(lambda c1,c2,c3 : (c1,c2,c3),ArrayType(IntegerType()))
df = df.withColumn('features',udf1(df['cat_var_1'],df['cat_var_2_final'],df['cat_var_3_final']))