Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 在Spark中,如何仅对前N个频繁值进行一次热编码?_Scala_Apache Spark_Apache Spark Sql_One Hot Encoding - Fatal编程技术网

Scala 在Spark中,如何仅对前N个频繁值进行一次热编码?

Scala 在Spark中,如何仅对前N个频繁值进行一次热编码?,scala,apache-spark,apache-spark-sql,one-hot-encoding,Scala,Apache Spark,Apache Spark Sql,One Hot Encoding,在我的数据帧df中,我有一个列my_category,其中我有不同的值,我可以使用以下方法查看值计数: df.groupBy("my_category").count().show() value count a 197 b 166 c 210 d 5 e 2 f 9 g 3 现在,我想在这个列上应用一个热编码(OHE),但只针对顶部的N频繁值(比如N=3),并将所有剩余的不频繁值放在一个虚拟列中(比如,“默认”)。例如,输出应类

在我的数据帧df中,我有一个列
my_category
,其中我有不同的值,我可以使用以下方法查看值计数:

df.groupBy("my_category").count().show()

value   count
a    197
b    166
c    210
d      5
e      2
f      9
g      3
现在,我想在这个列上应用一个热编码(OHE),但只针对顶部的
N
频繁值(比如
N=3
),并将所有剩余的不频繁值放在一个虚拟列中(比如,“默认”)。例如,输出应类似于:

a  b  c  default
0  0  1  0
1  0  0  0
0  1  0  0
1  0  0  0
...
0  0  0  1
0  0  0  1
...
如何在Spark/Scala中执行此操作?

注:
我知道如何在Python中实现这一点,例如,首先为每个唯一值构建一个基于频繁的字典,然后通过逐个检查值来创建OHE向量,将不频繁的值放入“默认”列。

自定义函数可以编写为,在特定列上应用一个热编码(OHE),仅适用于前N个频繁值(假设N=3)

它与Python相对类似,1)构建一个基于Topn频繁的数据帧/字典。2) 旋转前n个频繁数据帧,即创建OHE向量。3) 左键连接给定的数据帧和数据透视帧,将null替换为0,即默认的OHE向量

import org.apache.spark.sql.DataFrame
import org.apache.spark.sql.functions.{col, lit, when}
import org.apache.spark.sql.Column

import spark.implicits._
val df = spark
  .sparkContext
  .parallelize(Seq("a", "b", "c", "a", "b", "c", "d", "e", "a", "b", "f", "a", "g", "a", "b", "c", "a", "d", "e", "f", "a", "b", "g", "b", "c", "f", "a", "b", "c"))
  .toDF("value")

val oheEncodedDF = oheEncoding(df, "value", 3)


def oheEncoding(df: DataFrame, colName: String, n: Int): DataFrame = {
  df.createOrReplaceTempView("data")
  val topNDF = spark.sql(s"select $colName, count(*) as count from data group by $colName order by count desc limit $n")

  val pivotTopNDF = topNDF
    .groupBy(colName)
    .pivot(colName)
    .count()
    .withColumn("default", lit(1))

  val joinedTopNDF = df.join(pivotTopNDF, Seq(colName), "left").drop(colName)

  val oheEncodedDF = joinedTopNDF
    .na.fill(0, joinedTopNDF.columns)
    .withColumn("default", flip(col("default")))

   oheEncodedDF
}

def flip(col: Column): Column = when(col === 1, lit(0)).otherwise(lit(1))

下面的一个相关问题:我有n列,在这些列上应用了常规OHE,然后使用VectorAssembler,如:
val s1=new StringIndexer()…/n例如sIndexers val fE=new onehotcoderestimator().setInputCols(数组(s1.getOutputCol),…).setOutputCols(数组(“enc_s1”),val vE=new VectorAssembler().setInputCols(fE.getOutputCols)…。
现在,如何扩展OHE TopN()作为我的管道的一部分?我想要的oheEncodingTopN()不能引用“实际”数据帧,因为它将是管道的一部分(应用于列车/测试)。扩展原始OneHotEncoderEstimator.scala?还有其他选择吗?@YaleBD我不知道你到底想做什么,但是可能会以某种方式调用oheEncodingTopN()。我理解。。。基本上,我正在尝试构建一个矢量汇编程序,以便它能够接收来自自定义OneHotEncoder的输出。我想要的oheEncodingTopN()不能引用“实际”数据帧(就像在函数中一样),因为它将是管道的一部分(应用于trainData/testData)。因此,我正在寻找一种解决方案,它应该作为管道中的一个单独的阶段,而不是直接对数据进行操作的函数。我试着在这里解释:@YaleBD哦,现在我可以叙述了,我来看看。