Nik*_*shi 6 scala apache-spark spark-csv apache-spark-ml apache-spark-mllib
我正在将CSV文件(使用spark-csv)导入到DataFrame
具有空String
值的文件中.应用时OneHotEncoder
,应用程序崩溃并出错requirement failed: Cannot have an empty string for name.
.有没有办法解决这个问题?
val df = sqlContext.createDataFrame(Seq(
(0, "a"),
(1, "b"),
(2, "c"),
(3, ""), //<- original example has "a" here
(4, "a"),
(5, "c")
)).toDF("id", "category")
val indexer = new StringIndexer()
.setInputCol("category")
.setOutputCol("categoryIndex")
.fit(df)
val indexed = indexer.transform(df)
val encoder = new OneHotEncoder()
.setInputCol("categoryIndex")
.setOutputCol("categoryVec")
val encoded = encoder.transform(indexed)
encoded.show()
Run Code Online (Sandbox Code Playgroud)
这很烦人,因为缺失/空值是一种非常普遍的情况.
提前谢谢,Nikhil
由于OneHotEncoder
/ OneHotEncoderEstimator
不接受名称的空字符串,否则您将收到以下错误:
java.lang.IllegalArgumentException:要求失败:名称不能包含空字符串.在scala.Predef $ .require(Predef.scala:233)atg.apache.spark.ml.attribute.Attribute $$ anonfun $ 5.apply(attributes.scala:33)at org.apache.spark.ml.attribute. Attribute $$ anonfun $ 5.apply(attributes.scala:32)[...]
我就是这样做的:(还有其他办法,rf.@Anthony的回答)
我将创建一个UDF
处理空类别:
import org.apache.spark.sql.functions._
def processMissingCategory = udf[String, String] { s => if (s == "") "NA" else s }
Run Code Online (Sandbox Code Playgroud)
然后,我将在列上应用UDF:
val df = sqlContext.createDataFrame(Seq(
(0, "a"),
(1, "b"),
(2, "c"),
(3, ""), //<- original example has "a" here
(4, "a"),
(5, "c")
)).toDF("id", "category")
.withColumn("category",processMissingCategory('category))
df.show
// +---+--------+
// | id|category|
// +---+--------+
// | 0| a|
// | 1| b|
// | 2| c|
// | 3| NA|
// | 4| a|
// | 5| c|
// +---+--------+
Run Code Online (Sandbox Code Playgroud)
现在,您可以回到您的转型
val indexer = new StringIndexer().setInputCol("category").setOutputCol("categoryIndex").fit(df)
val indexed = indexer.transform(df)
indexed.show
// +---+--------+-------------+
// | id|category|categoryIndex|
// +---+--------+-------------+
// | 0| a| 0.0|
// | 1| b| 2.0|
// | 2| c| 1.0|
// | 3| NA| 3.0|
// | 4| a| 0.0|
// | 5| c| 1.0|
// +---+--------+-------------+
// Spark <2.3
// val encoder = new OneHotEncoder().setInputCol("categoryIndex").setOutputCol("categoryVec")
// Spark +2.3
val encoder = new OneHotEncoderEstimator().setInputCols(Array("categoryIndex")).setOutputCols(Array("category2Vec"))
val encoded = encoder.transform(indexed)
encoded.show
// +---+--------+-------------+-------------+
// | id|category|categoryIndex| categoryVec|
// +---+--------+-------------+-------------+
// | 0| a| 0.0|(3,[0],[1.0])|
// | 1| b| 2.0|(3,[2],[1.0])|
// | 2| c| 1.0|(3,[1],[1.0])|
// | 3| NA| 3.0| (3,[],[])|
// | 4| a| 0.0|(3,[0],[1.0])|
// | 5| c| 1.0|(3,[1],[1.0])|
// +---+--------+-------------+-------------+
Run Code Online (Sandbox Code Playgroud)
编辑:
@Anthony在Scala中的解决方案:
df.na.replace("category", Map( "" -> "NA")).show
// +---+--------+
// | id|category|
// +---+--------+
// | 0| a|
// | 1| b|
// | 2| c|
// | 3| NA|
// | 4| a|
// | 5| c|
// +---+--------+
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助!
是的,这有点棘手,但也许您可以将空字符串替换为肯定与其他值不同的内容。请注意,我使用的是 pyspark DataFrameNaFunctions API,但Scala应该类似。
df = sqlContext.createDataFrame([(0,"a"), (1,'b'), (2, 'c'), (3,''), (4,'a'), (5, 'c')], ['id', 'category'])
df = df.na.replace('', 'EMPTY', 'category')
df.show()
+---+--------+
| id|category|
+---+--------+
| 0| a|
| 1| b|
| 2| c|
| 3| EMPTY|
| 4| a|
| 5| c|
+---+--------+
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6294 次 |
最近记录: |