过滤阶段在RDD沿袭重新执行中丢失

时间:2016-02-12 08:54:00

标签: apache-spark

我对RDD和血统图有疑问。让我用一个例子来说明: 我有一个如下所示的数据文件:

ID; parent; level; type;content; Budget;
999999 ;;a;Total;total; 313344394;
01 ;;a;Part 1;Chancellery of the President of the Republic of Poland; 171524;
02 ;;a;Part 2;Chancellery of the Sejm; 430780;
03 ;;a;Part 3;OFFICE OF THE SENATE; 176212;
04 ;;a;Part 4;SUPREME COURT; 88161;

请注意,对于上一个预算字段,有一个前导空格。 所以我读入数据,创建一个由选定列组成的RDD:

scala>  val baseRDD=sc.textFile(dataFile)
baseRDD: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[103] at textFile at <console>:29

scala> val budgetRDD=baseRDD.map(_.split(";")).map(x => (x(0),x(4), x(5))) 
budgetRDD: org.apache.spark.rdd.RDD[(String, String, String)] = MapPartitionsRDD[101] at map at <console>:31

现在,我过滤掉标题行并获取最后一列作为int:

scala> val headerRow=budgetRDD.first
headerRow: (String, String, String) = (ID,content,Budget)

scala> val idBudgetRDD = budgetRDD.filter(_!=headerRow).map{case(id,name,money) => 
(id,money.toInt)}

idBudgetRDD: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[105] at map at <console>:46

scala> idBudgetRDD.toDebugString
res143: String = 
(2) MapPartitionsRDD[105] at map at <console>:46 []
|  MapPartitionsRDD[104] at filter at <console>:46 []
|  MapPartitionsRDD[101] at map at <console>:31 []
|  MapPartitionsRDD[100] at map at <console>:31 []
|  MapPartitionsRDD[99] at textFile at <console>:29 []
|  /home/user/poland_budget_2011_small.txt HadoopRDD[98] at textFile at <console>:29 []

因此上面的血统图清楚地显示了过滤步骤。 现在我看看我的数据并得到一个错误:

scala> idBudgetRDD.take(2)
16/02/12 03:43:46 ERROR Executor: Exception in task 0.0 in stage 146.0 (TID 179)
java.lang.NumberFormatException: For input string: " 313344394"
at     java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:569)
at java.lang.Integer.parseInt(Integer.java:615)

由于预算栏中的领先空间,这是可以理解的。 因此,我编辑并删除了数据文件中的前导空格,而不是使用trim:

ID; parent; level; type;content;Budget;
999999 ;;a;Total;total;313344394;
01 ;;a;Part 1;Chancellery of the President of the Republic of Poland;171524;
02 ;;a;Part 2;Chancellery of the Sejm;430780;
03 ;;a;Part 3;OFFICE OF THE SENATE;176212;
04 ;;a;Part 4;SUPREME COURT;88161;

进行了此更改后,使用上面的沿袭图,我的期望是重新运行take操作会重新执行沿袭图并产生所需的结果。但事实并非如此,而是我得到了另一个错误,表明未应用排除标题行的过滤步骤:

scala> idBudgetRDD.take(2)
16/02/12 03:47:03 ERROR Executor: Exception in task 0.0 in stage 147.0 (TID 180)
java.lang.NumberFormatException: For input string: "Budget"
at     java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)

有人可以解释发生了什么吗?我的想法是,由于懒惰的评估和沿袭,修复数据文件并重新执行take将导致谱系图完全重新运行。

1 个答案:

答案 0 :(得分:0)

事实证明我上面使用的过滤器是固定的,因此在我修改文件后它不再适用。我能够通过指定一个依赖于匹配ID字符串的过滤器来解决这个问题,如下所示:

val idBudgetRDD = budgetRDD.filter(! _.0.startsWith("ID;")).map{case(id,name,money) => (id, money.toInt)} 

这总是与标题行匹配,重新运行take会产生正确的结果。