【问题标题】:How to identify null fields in a csv file?如何识别 csv 文件中的空字段?
【发布时间】:2017-12-04 00:58:52
【问题描述】:

我正在使用 Spark 2.1.1 和 Scala 2.11.8。

我必须从 csv 文件中读取数据,其列的范围从最小 6 到最大 8。我必须拆分 9 个条目,一旦拆分,第 0 到 5 列将始终包含数据。但是,第 6 到第 8 列中可能存在或不存在数据。我使用以下方法将所需的列分隔并存储在 RDD 中:

val read_file = sc.textFile("Path to input file");

val uid = read_file.map(line => {var arr = line.split(","); (arr(2).split(":")(0),arr(3),arr(4).split(":")(0),arr(5).split(":")(0),arr(6).split(":")(0),arr(7).split(":")(0),arr(8).split(":")(0))})

现在,在获得的 RDD 'uid' 中,第 0 到第 3 列将始终被填充,但第 4 到第 7 列可能有数据,也可能没有数据。例如:我从中读取数据的 csv 文件,

2017-05-09 21:52:42 , 1494391962 , p69465323_serv80i:10:450 , 7 , fb_406423006398063:396560, guest_861067032060185_android:671051, fb_100000829486587:186589, fb_100007900293502:407374, fb_172395756592775:649795

2017-05-09 21:52:42 , 1494391962 , z67265107_serv77i:4:45 , 2:Re , fb_106996523208498:110066, fb_274049626104849:86632, fb_111857069377742:69348, fb_127277511127344:46246

2017-05-09 21:52:42 , 1494391962 , v73392772_serv33i:9:1400 , 1:4x , c2eb11fd-99dc-4dee-a75c-bc9bfd2e0ae4iphone:314129, fb_217409795286934:294262

可以看出,第一个条目已填充所有 9 列,第二个条目已填充 8 个,第三个条目仅填充了 6 列。

从获得的 RDD 中,我必须将列 arr(1)(0) 与列 arr(3)(0) 映射到 arr(7)(0)。列 1 的映射应该只对填充列进行从 3 到 7。3 到 7 之间的空列不必与第 1 列映射。我试图使用 for 循环来做到这一点:

一旦我在执行语句 val uid = read_file.map() 后得到了这个:

(String, String, String, String, String, String, String) = (" p69465323_serv80i"," 7 "," fb_406423006398063"," guest_861067032060185_android"," fb_100000829486587"," fb_100007900293502"," fb_172395756592775")

我愿意:

for (var x <= 5 to 7) { if var arr => (arr(x) != null) {
val pairedRdd = uid.map(x => ((x._1, x._3), (x._1, x._4), (x._1, x._5), (x._1, x._6), (x._1, x._7)) ) }

这将适用于给定数据示例中的第一条语句,但不适用于第二条和第三条。

我承认逻辑是错误的,但这只是为了传达我正在尝试做的事情的想法。

P.S : 不允许使用 Spark SQL。

【问题讨论】:

  • 缺少的列,它们是否按顺序排列?我的意思是说,当缺少一列时,列号是第 7 列,对吗?
  • 正确。缺少的列将始终按顺序排列。
  • 您有 9 列。您能否查看您的问题以更新不正确的信息?
  • 完成。我已经提到,第二行本身的列从 0 开始。列从 0 到 8。
  • 您所需输出的样本也应该有所帮助:)

标签: arrays scala csv apache-spark mapping


【解决方案1】:

你可以这样做

val read_file = sc.textFile("Path to input file")
val uid = read_file.map(line => line.split(",")).map(array => array.map(arr => {
    if(arr.contains(":")) (array(2).split(":")(0), arr.split(":")(0))
    else (array(2).split(":")(0), arr)
}))

现在做

uid.map(array => array.drop(2)).map(array => array.toSeq)

会给你rdd as

WrappedArray(( p69465323_serv80i, p69465323_serv80i), ( p69465323_serv80i, 7 ), ( p69465323_serv80i, fb_406423006398063), ( p69465323_serv80i, guest_861067032060185_android), ( p69465323_serv80i, fb_100000829486587), ( p69465323_serv80i, fb_100007900293502), ( p69465323_serv80i, fb_172395756592775))
WrappedArray(( z67265107_serv77i, z67265107_serv77i), ( z67265107_serv77i, 2), ( z67265107_serv77i, fb_106996523208498), ( z67265107_serv77i, fb_274049626104849), ( z67265107_serv77i, fb_111857069377742), ( z67265107_serv77i, fb_127277511127344))
WrappedArray(( v73392772_serv33i, v73392772_serv33i), ( v73392772_serv33i, 1), ( v73392772_serv33i, c2eb11fd-99dc-4dee-a75c-bc9bfd2e0ae4iphone), ( v73392772_serv33i, fb_217409795286934))

而做

uid.map(array => array.drop(2)).flatMap(array => array)

会给你rdd

( p69465323_serv80i, p69465323_serv80i)
( p69465323_serv80i, 7 )
( p69465323_serv80i, fb_406423006398063)
( p69465323_serv80i, guest_861067032060185_android)
( p69465323_serv80i, fb_100000829486587)
( p69465323_serv80i, fb_100007900293502)
( p69465323_serv80i, fb_172395756592775)
( z67265107_serv77i, z67265107_serv77i)
( z67265107_serv77i, 2)
( z67265107_serv77i, fb_106996523208498)
( z67265107_serv77i, fb_274049626104849)
( z67265107_serv77i, fb_111857069377742)
( z67265107_serv77i, fb_127277511127344)
( v73392772_serv33i, v73392772_serv33i)
( v73392772_serv33i, 1)
( v73392772_serv33i, c2eb11fd-99dc-4dee-a75c-bc9bfd2e0ae4iphone)
( v73392772_serv33i, fb_217409795286934)

选择是你的

【讨论】:

  • 这和我要找的很接近,但是我上面提到的 uid.first() 语句的输出是我要执行操作的 RDD,即 uid RDD 的第一列映射到第 4 到第 7 列,前提是它们不为空。只需跳过空列。此外,必须对超过 5000 万个条目执行此映射,每个条目的列数各不相同。这就是我尝试使用循环机制的原因。
  • 所以你只想要有 9 个字段的输出,对吗?
  • 不不,我在 UID RDD 中得到的输出,第 3 和第 4 列将始终被填充。第 5 到 7 列可以填满也可以为空。我必须将第一列与 3 - 7 之间的可用列进行映射,例如,如果仅填充第 3、4、5 列,我必须将第 1 列映射到第 3、4、5 列。如果第 3、4、5、6、7 列已填满,我必须将第 1 列映射到 3、4、5、6、7 等。我必须检查每个条目中从 5 到 7 的空列。如果为null,我不映射到第1列。如果不为null,我映射到第1列。但是没有条目可以省略,所有条目都必须映射。我希望这能传达我想要做的事情:)
  • 所以这意味着如果 5 到 7 为空,那么每个 5 到 7 得到 (array(1), array(1)),是这样吗?
  • 说我得到了 ("p","7","fb1","fb2","fb3","fb4","fb5")。现在第 3 到 7 列不是空白的,所以我映射列 (1,3);(1,4);(1,5);(1,6);(1,7)。但是如果第 5,6,7 列为空,我映射 (1,3);(1,4)。如果第 7 列为空,我映射 (1,3);(1,4);(1,5);(1,6) 等等。
猜你喜欢
  • 2012-09-01
  • 2019-03-06
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多