【问题标题】:How to use string variables in VectorAssembler in Pyspark如何在 Pyspark 的 VectorAssembler 中使用字符串变量
【发布时间】:2018-03-02 02:27:13
【问题描述】:

我想在 Pyspark 上运行随机森林算法。 Pyspark documentation 中提到 VectorAssembler 只接受数字或布尔数据类型。那么,如果我的数据包含 Stringtype 变量,比如城市名称,我是否应该对它们进行一次性编码以便进一步进行随机森林分类/回归?

这是我一直在尝试的代码,输入文件是here

train=sqlContext.read.format('com.databricks.spark.csv').options(header='true').load('filename')
drop_list = ["Country", "Carrier", "TrafficType","Device","Browser","OS","Fraud","ConversionPayOut"]
from pyspark.sql.types import DoubleType
train = train.withColumn("ConversionPayOut", train["ConversionPayOut"].cast("double"))#only this variable is actually double, rest of them are strings
junk = train.select([column for column in train.columns if column in drop_list])
transformed = assembler.transform(junk)

我不断收到IllegalArgumentException: u'Data type StringType is not supported.' 的错误

P.S.:很抱歉提出一个基本问题。我来自 R 背景。在 R 中,当我们做随机森林时,不需要将分类变量转换为数值变量。

【问题讨论】:

  • 相关的question 也很有用。您只需要将indexers 连接到您的管道中。

标签: pyspark random-forest


【解决方案1】:

是的,您应该使用StringIndexer,也许与OneHotEncoder 一起使用。您可以在链接的文档中找到有关这两者的更多信息。

【讨论】:

    【解决方案2】:
    Following is the example -
    Schema
     |-- age: integer (nullable = true)
     |-- workclass: string (nullable = true)
     |-- fnlwgt: double (nullable = true)
     |-- education: string (nullable = true)
     |-- education-num: double (nullable = true)
     |-- marital-status: string (nullable = true)
     |-- occupation: string (nullable = true)
     |-- relationship: string (nullable = true)
     |-- race: string (nullable = true)
     |-- sex: string (nullable = true)
     |-- capital-gain: double (nullable = true)
     |-- capital-loss: double (nullable = true)
     |-- hours-per-week: double (nullable = true)
     |-- native-country: string (nullable = true)
     |-- income: string (nullable = true)
    
            // Deal with Categorical Columns
            // Transform string type columns to string indexer 
            val workclassIndexer = new StringIndexer().setInputCol("workclass").setOutputCol("workclassIndex")
            val educationIndexer = new StringIndexer().setInputCol("education").setOutputCol("educationIndex")
            val maritalStatusIndexer = new StringIndexer().setInputCol("marital-status").setOutputCol("maritalStatusIndex")
            val occupationIndexer = new StringIndexer().setInputCol("occupation").setOutputCol("occupationIndex")
            val relationshipIndexer = new StringIndexer().setInputCol("relationship").setOutputCol("relationshipIndex")
            val raceIndexer = new StringIndexer().setInputCol("race").setOutputCol("raceIndex")
            val sexIndexer = new StringIndexer().setInputCol("sex").setOutputCol("sexIndex")
            val nativeCountryIndexer = new StringIndexer().setInputCol("native-country").setOutputCol("nativeCountryIndex")
            val incomeIndexer = new StringIndexer().setInputCol("income").setOutputCol("incomeIndex")
    
            // Transform string type columns to string indexer 
            val workclassEncoder = new OneHotEncoder().setInputCol("workclassIndex").setOutputCol("workclassVec")
            val educationEncoder = new OneHotEncoder().setInputCol("educationIndex").setOutputCol("educationVec")
            val maritalStatusEncoder = new OneHotEncoder().setInputCol("maritalStatusIndex").setOutputCol("maritalVec")
            val occupationEncoder = new OneHotEncoder().setInputCol("occupationIndex").setOutputCol("occupationVec")
            val relationshipEncoder = new OneHotEncoder().setInputCol("relationshipIndex").setOutputCol("relationshipVec")
            val raceEncoder = new OneHotEncoder().setInputCol("raceIndex").setOutputCol("raceVec")
            val sexEncoder = new OneHotEncoder().setInputCol("sexIndex").setOutputCol("sexVec")
            val nativeCountryEncoder = new OneHotEncoder().setInputCol("nativeCountryIndex").setOutputCol("nativeCountryVec")
            val incomeEncoder = new StringIndexer().setInputCol("incomeIndex").setOutputCol("label")
    
        // Assemble everything together to be ("label","features") format
            val assembler = (new VectorAssembler()
              .setInputCols(Array("workclassVec", "fnlwgt", "educationVec", "education-num", "maritalVec", "occupationVec", "relationshipVec", "raceVec", "sexVec", "capital-gain", "capital-loss", "hours-per-week", "nativeCountryVec"))
              .setOutputCol("features"))
    
     ///////////////////////////////
        // Set Up the Pipeline ///////
        /////////////////////////////
        import org.apache.spark.ml.Pipeline
    
        val lr = new LogisticRegression()
    
        val pipeline = new Pipeline().setStages(Array(workclassIndexer, educationIndexer, maritalStatusIndexer, occupationIndexer, relationshipIndexer, raceIndexer, sexIndexer, nativeCountryIndexer, incomeIndexer, workclassEncoder, educationEncoder, maritalStatusEncoder, occupationEncoder, relationshipEncoder, raceEncoder, sexEncoder, nativeCountryEncoder, incomeEncoder, assembler, lr))
    
        // Fit the pipeline to training documents.
        val model = pipeline.fit(training)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-28
      • 2018-04-16
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多