有条件地映射Scala / Spark中CSV文件中的行以生成另一个CSV文件

时间:2016-07-30 10:47:37

标签: scala csv apache-spark etl

我是Scala / Spark的新手,我已经陷入了深渊。几个星期以来,我一直在努力为Scala 2.11.8找到一个看似简单的问题的解决方案,但一直无法为它找到一个好的解决方案。 我有一个接近150 GB的csv格式的大型数据库,有大量的空值,需要根据各列的值进行简化和清理。

原始CSV文件的架构如下:

  • 第1栏:双重
  • 第2栏:整数
  • 第3栏:双重
  • 第4栏:双重
  • 第5栏:整数
  • 第6栏:双重
  • 第7栏:整数

因此,我想有条件地映射CSV文件的所有行,并将结果导出到另一个CSV文件,每行包含以下条件:

  1. 如果第4列的值不为null,则该行的第4,5,6和7列的值应存储为名为lastValuesOf4to7的数组。 (在数据集中,如果第4列中的元素不为空,则第1,2和3列为空,可以忽略)

  2. 如果第3列的值不为null,那么第1列,第2列和第3列的值以及lastValuesOf4to7数组中的四个元素(如上所述)应作为新行导出到另一个CSV文件中叫做condensed.csv。 (在数据集中,如果第3列中的元素不为空,则第4,5,6和7列为空,可以忽略)

  3. 所以最后我应该得到一个名为condensed.csv的csv文件,该文件有7列。

    我已尝试在Scala中使用以下代码,但未能取得进一步进展:

    import scala.io.Source
    
    object structuringData {
      def main(args: Array[String]) {
    
      val data = Source.fromFile("/path/to/file.csv") 
    
      var lastValuesOf4to7 = Array("0","0","0","0")
    
      val lines = data.getLines // Get the lines of the file
    
      val splitLine = lines.map(s => s.split(',')).toArray // This gives an out of memory error since the original file is huge.
    
    
    
      data.close
      }
    }
    

    正如您从上面的代码中看到的那样,我尝试将其移动到一个数组中但由于无法单独处理每一行而无法继续进行。

    我非常肯定在Scala / Spark上处理csv文件必须有直接的解决方案。

2 个答案:

答案 0 :(得分:1)

使用Spark-csv包,然后使用Sql查询查询数据并根据您的用例制作过滤器,然后在最后导出它。

如果您使用的是spark 2.0.0,那么spark-csv将出现在spark-sql中,否则如果您使用的是旧版本,则相应地添加依赖项。

您可以在此处找到指向spark-csv的链接。

您还可以在此处查看示例:http://blog.madhukaraphatak.com/analysing-csv-data-in-spark/

答案 1 :(得分:0)

感谢您的回复。我设法使用Bash Script自己创建了一个解决方案。我必须先从空白的condensed.csv文件开始。我的代码显示了实现这一目标是多么容易:

#!/bin/bash
OLDIFS=$IFS
IFS=","
last1=0
last2=0
last3=0
last4=0
while read f1 f2 f3 f4 f5 f6 f7
do
    if [[ $f4 != "" ]];
    then 
        last1=$f4
        last2=$f5
        last3=$f6
        last4=$f7

    elif [[ $f3 != "" ]];
    then 
        echo "$f1,$f2,$f3,$last1,$last2,$last3,$last4" >> path/to/condensed.csv
    fi

done < $1
IFS=$OLDIFS

如果使用名称extractcsv.sh保存脚本,则应使用以下格式运行:

$ ./extractcsv.sh path/to/original/file.csv

这只能证实我的观察结果是ETL在Bash上比在Scala中更容易。谢谢你的帮助。