当前位置: 首页 > 知识库问答 >
问题:

字段中的空值会生成MatchError

乜嘉悦
2023-03-14

以下是有趣的:

val rddSTG = sc.parallelize(
      List ( ("RTD","ANT","SOYA BEANS", "20161123", "20161123", 4000, "docid11", null, 5) , 
             ("RTD","ANT","SOYA BEANS", "20161124", "20161123", 6000, "docid11",  null, 4) ,
             ("RTD","ANT","BANANAS", "20161124", "20161123", 7000, "docid11", null, 9) ,    
             ("HAM","ANT","CORN", "20161123", "20161123", 1000, "docid22", null, 33),
             ("LIS","PAR","BARLEY", "20161123", "20161123", 11111, "docid33", null, 44)
           )
                          )

val dataframe = rddSTG.toDF("ORIG", "DEST", "PROD", "PLDEPDATE", "PLARRDATE", "PLCOST", "docid", "ACTARRDATE", "mutationseq")
dataframe.createOrReplaceTempView("STG")
spark.sql("SELECT * FROM STG ORDER BY PLDEPDATE DESC").show()

它会生成如下错误:

scala.MatchError: Null (of class scala.reflect.internal.Types$TypeRef$$anon$6)

只要我将其中一个空值更改为非空值,它就会工作。我想我明白了,因为在这个领域无法做出任何推断,但这确实看起来很奇怪。想法?

共有3个答案

楚威
2023-03-14

简单的解决方案是添加测试行

val rddSTG = sc.parallelize(
  Seq ( ("RTD","ANT","SOYA BEANS", "20161123", "20161123", 4000, "docid11", null, 5) ,
    ("RTD","ANT","SOYA BEANS", "20161124", "20161123", 6000, "docid11",  null, 4) ,
    ("RTD","ANT","BANANAS", "20161124", "20161123", 7000, "docid11", null, 9) ,
    ("HAM","ANT","CORN", "20161123", "20161123", 1000, "docid22", null, 33),
    ("LIS","PAR","BARLEY", "20161123", "20161123", 11111, "docid33", null, 44),
    ("test","test","test", "test", "test", 0, "test", "", 0)
    )
    )

过滤器dataframe被创建为之后的测试行

val dataframe = rddSTG.toDF("ORIG", "DEST", "PROD", "PLDEPDATE", "PLARRDATE", "PLCOST", "docid", "ACTARRDATE", "mutationseq")
                      .filter(!(col("ORIG") === "test"))

您可以将其余逻辑应用为

dataframe.createOrReplaceTempView("STG")
spark.sql("SELECT * FROM STG ORDER BY PLDEPDATE DESC").show()

您应该将输出设置为

+----+----+----------+---------+---------+------+-------+----------+-----------+
|ORIG|DEST|      PROD|PLDEPDATE|PLARRDATE|PLCOST|  docid|ACTARRDATE|mutationseq|
+----+----+----------+---------+---------+------+-------+----------+-----------+
| RTD| ANT|SOYA BEANS| 20161124| 20161123|  6000|docid11|      null|          4|
| RTD| ANT|   BANANAS| 20161124| 20161123|  7000|docid11|      null|          9|
| RTD| ANT|SOYA BEANS| 20161123| 20161123|  4000|docid11|      null|          5|
| HAM| ANT|      CORN| 20161123| 20161123|  1000|docid22|      null|         33|
| LIS| PAR|    BARLEY| 20161123| 20161123| 11111|docid33|      null|         44|
+----+----+----------+---------+---------+------+-------+----------+-----------+

我希望这能有所帮助

慎志国
2023-03-14

我不太确定错误背后的原因,但我猜测它的发生是因为Null不能是dataframe列的数据类型。因为您的第二列是null,这是trait的一部分。由于它们位于层次结构的底部,因此不能实例化为任何其他类型。但是,null是所有内容的子类型,因此,即使您将其中任何一个更改为字符串,也会使列变为字符串类型。这只是一个假设。

但是,对于您的案例,定义一个案例类就可以了。

val rdd = sc.parallelize(List ( ("RTD","ANT","SOYA BEANS", "20161123", "20161123", 4000, "docid11", null, 5) , 
            ("RTD","ANT","SOYA BEANS", "20161124", "20161123", 6000, "docid11",  null, 4) ,
            ("RTD","ANT","BANANAS", "20161124", "20161123", 7000, "docid11", null, 9) ,    
            ("HAM","ANT","CORN", "20161123", "20161123", 1000, "docid22", null, 33),
            ("LIS","PAR","BARLEY", "20161123", "20161123", 11111, "docid33", null, 44)))
case class df_schema (ORIG: String, DEST: String, PROD: String, PLDEPDATE:String, PLARRDATE: String, PLCOSTDATE: Int, DOCID: String, ACTARRDATE: String, MUTATIONSEQ: Int)
val rddSTG = rdd.map( x=> df_schema(x._1, x._2, x._3, x._4, x._5, x._6, x._7, x._8, x._9 ) )
val dataframe = sqlContext.createDataFrame(rddSTG)
高宏峻
2023-03-14

问题是-任何在scala中都是泛型类型。在您的情况下,NULL被视为ANY类型。

Spark根本不知道如何序列化NULL。

我们应该显式地提供一些特定的类型。

由于无法将null分配给Scala中的原始类型,因此您可以使用String来匹配列的其他值的数据类型。

所以试试这个:

case class Record(id: Int, name: String, score: Int, flag: String)
val sampleRdd = spark.sparkContext.parallelize(
  Seq(
    (1, null.asInstanceOf[String], 100, "YES"),
    (2, "RAKTOTPAL", 200, "NO"),
    (3, "BORDOLOI", 300, "YES"),
    (4, null.asInstanceOf[String], 400, "YES")))

sampleRdd.toDF("ID", "NAME", "SCORE","FLAG")

这样,df将保留空值。

案例类

case class Record(id: Int, name: String, score: Int, flag: String)

val sampleRdd = spark.sparkContext.parallelize(
  Seq(
    Record(1, null.asInstanceOf[String], 100, "YES"),
    Record(2, "RAKTOTPAL", 200, "NO"),
    Record(3, "BORDOLOI", 300, "YES"),
    Record(4, null.asInstanceOf[String], 400, "YES")))
sampleRdd.toDF()
 类似资料:
  • null 我看到的是一般的注释 可用于排除空值。我不能使用此方法,因为我仍然希望在json中看到具有空值的空字段 可以用来排除空值和“不存在”的值。我不能使用这个,因为我仍然想看到JSON中的空字段和空字段。与相同 所以我的问题是,如果我不指定这些属性中的任何一个,我能实现我想要的吗?换句话说,如果我没有指定其中的任何一个,那么Jackson的行为是显示所有在动态意义上具有空值的字段吗?我主要关心

  • 问题内容: 显然,如果元素中没有结束标签而没有匹配的开始标签,则大多数(如果不是全部)浏览器将在其位置生成一个空段: 即使end标记周围存在任何文本,也不会将其作为此元素的一部分-它将始终为空,并且文本节点将始终独立存在: 如果以上内容都包裹在和标记中,…我将让您猜测会发生什么: 有趣的是,如果标记之前没有或标记,则除IE9和更早版本之外的所有浏览器都 不会 生成空段落(另一方面,IE≤9始终会创

  • 在Postgres9.5中,我无法从JSONB字段中的属性中选择非空值 我还尝试使用NotNull。 当我运行其中一个时,我收到错误42883。“错误:运算符不存在。JSONB->>布尔提示:没有与给定名称和参数类型匹配的运算符。您可能需要添加显式类型转换。”

  • 我有这个生成动态字段的示例代码。 我的问题是我不知道如何将数据插入数据库。 我尝试过内爆,但结果不是我想要的格式。 这是我的专栏(id、姓名、糖果、水果、饮料) 所以如果我生成3行,它应该像这样插入 事实上,我不知道这是否可能。谢啦 小提琴 https://jsfiddle.net/jqj1h4vb/2/

  • 我正在编写一个使用javafx FXML生成日志文件的程序。是否可以生成一组与仪器相关联的文本字段。示例:型号:Sn:Tg:Gas: 我需要收集每个仪器的信息,但有些地方有5个单位,有些只有1个。我正在寻找有字段生成从用户输入多少他们需要。这是我能做的吗?