【问题标题】:Spark - How to create a Spark dataframe that contains array of values in one of its columns for countVectorizer modelSpark - 如何为 countVectorizer 模型创建一个包含值数组的 Spark 数据框
【发布时间】:2017-09-05 07:33:24
【问题描述】:

我正在尝试执行 Spark 的 countVectorizer 模型。作为此要求的一部分,我正在读取一个 csv 文件并从中创建一个 Dataframe (inp_DF)。

它有 3 列,如下所示

+--------------+--------+-------+
|         State|Zip Code|Country|
+--------------+--------+-------+
|      kentucky|   40205|     us|
|       indiana|   47305|     us|
|greater london|    sw15|     gb|
|    california|   92707|     us|
|      victoria|    3000|     au|
|         paris|   75001|     fr|
|      illinois|   60608|     us|
|     minnesota|   55405|     us|
|    california|   92688|     us|
+--------------+--------+-------+

我需要在同一数据框中创建第 4 列,其中包含所有这 3 列的值数组,例如

|      kentucky|   40205|     us|   "kentucky","40205","us"
|       indiana|   47305|     us|   "indiana","47305","us"
|greater london|    sw15|     gb|   "greater london","sw15","gb"
|    california|   92707|     us|   "california","92707","us"
|      victoria|    3000|     au|   "victoria","3000","au"
|         paris|   75001|     fr|   "paris","75001","fr"
|      illinois|   60608|     us|   "illinois","60608","us"
|     minnesota|   55405|     us|   "minnesota","55405","us"
|    california|   92688|     us|   "california","92688","us"

问题 1:有没有像 .concat 这样简单的命令来实现这一点?

需要此数组,因为 countVectorizer 模型的输入应该是包含值数组的列。它不应该是下面错误消息中提到的字符串数据类型:

线程“主”java.lang.IllegalArgumentException 中的异常: 要求失败:列状态的类型必须等于以下之一 以下类型:[ArrayType(StringType,true), ArrayType(StringType,false)] 但实际上是 StringType 类型。在 scala.Predef$.require(Predef.scala:224) 在 org.apache.spark.ml.util.SchemaUtils$.checkColumnTypes(SchemaUtils.scala:58) 在 org.apache.spark.ml.feature.CountVectorizerParams$class.validateAndTransformSchema(CountVectorizer.scala:75) 在 org.apache.spark.ml.feature.CountVectorizer.validateAndTransformSchema(CountVectorizer.scala:123) 在 org.apache.spark.ml.feature.CountVectorizer.transformSchema(CountVectorizer.scala:188) 在 org.apache.spark.ml.PipelineStage.transformSchema(Pipeline.scala:74) 在 org.apache.spark.ml.feature.CountVectorizer.fit(CountVectorizer.scala:155) 在 org.apache.spark.examples.ml.CountVectorizerExample$.main(CountVectorizerExample.scala:54) 在 org.apache.spark.examples.ml.CountVectorizerExample.main(CountVectorizerExample.scala) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) Java HotSpot(TM) 客户端虚拟机警告:忽略选项 MaxPermSize=300m; 8.0 中移除了支持

我尝试从这 3 列输入数据帧创建一个数组,但数组元素包含在方括号 [ ] 中。

下面给出示例代码sn-p供您参考

// Read Input Dataset for countVectorizer Logic
val inp_data = spark.read.format("com.databricks.spark.csv").option("header", "True").option("inferSchema", "true")
      .option("treatEmptyValuesAsNulls", "true").option("nullValue", "")
      .load("Input.csv")

// Creating a Spark Dataframe from the Input Data
val inp_DF = inp_data.toDF()

// Creating an array from Spark Dataframe Columns
val inp_array = inp_DF.select("State","Zip Code","Country").collect()
      println(inp_array.mkString(","))

// fit a CountVectorizerModel from the corpus
val cvModel: CountVectorizerModel = new CountVectorizer()
      .setInputCol("State")
      .setOutputCol("features")
      .setVocabSize(4)
      .setMinDF(2)
      .fit(inp_DF)

问题 2:如何从这些数组元素中删除方括号 [] 并在数据框中使用数组的值创建一个新列?

问题 3:我们能否提供单列值作为 countVectorizer 模型的输入并获取特征作为输出?

【问题讨论】:

    标签: apache-spark spark-dataframe countvectorizer


    【解决方案1】:

    您可以使用array 函数将array column 创建为

    import org.apache.spark.sql.functions._
    val inp_array = inp_DF.withColumn("arrayColumn", array("State", "Zip Code", "Country"))
    

    这应该给你输出

    +-------------+--------+-------+-------------------------+
    |State        |Zip Code|Country|arrayColumn              |
    +-------------+--------+-------+-------------------------+
    |kentucky     |40205   |us     |[kentucky, 40205, us]    |
    |indiana      |47305   |us     |[indiana, 47305, us]     |
    |greaterlondon|sw15    |gb     |[greaterlondon, sw15, gb]|
    |california   |92707   |us     |[california, 92707, us]  |
    |victoria     |3000    |au     |[victoria, 3000, au]     |
    |paris        |75001   |fr     |[paris, 75001, fr]       |
    |illinois     |60608   |us     |[illinois, 60608, us]    |
    |minnesota    |55405   |us     |[minnesota, 55405, us]   |
    |california   |92688   |us     |[california, 92688, us]  |
    +-------------+--------+-------+-------------------------+
    

    你可以在你的CountVectorizerModel中使用这个dataframe作为

    val cvModel: CountVectorizerModel = new CountVectorizer()
      .setInputCol("arrayColumn")
      .setOutputCol("features")
      .setVocabSize(4)
      .setMinDF(2)
      .fit(inp_array)
    

    这回答了您的前两个问题。

    现在回答你的第三个问题。 您只能在CountVectorizerModel 中使用一列,但为此您需要将该列转换为ArrayType(StringType,true),这可以通过使用上述array 函数来完成。

    假设您想在CountVectorizerModel 中使用State 列。然后您可以通过执行将State 列的数据类型更改为array

    val single_arrayDF = inp_DF.withColumn("State", array("State"))
    

    并将其用作

     val cvModel: CountVectorizerModel = new CountVectorizer()
      .setInputCol("State")
      .setOutputCol("features")
      .setVocabSize(4)
      .setMinDF(2)
      .fit(single_arrayDF)
    

    希望回答对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-25
      • 2018-11-28
      相关资源
      最近更新 更多