代码之家  ›  专栏  ›  技术社区  ›  Gaurav Gupta

如何加载多行记录的CSV文件?

  •  10
  • Gaurav Gupta  · 技术社区  · 8 年前

    我使用Spark 2.3.0。

    作为Apache Spark的项目,我正在使用 this 要处理的数据集。尝试使用spark读取csv时,spark数据框中的行与csv中的正确行不对应(请参见示例csv here )文件。代码如下所示:

    answer_df = sparkSession.read.csv('./stacksample/Answers_sample.csv', header=True, inferSchema=True, multiLine=True);
    answer_df.show(2)
    

    输出

    +--------------------+-------------+--------------------+--------+-----+--------------------+
    |                  Id|  OwnerUserId|        CreationDate|ParentId|Score|                Body|
    +--------------------+-------------+--------------------+--------+-----+--------------------+
    |                  92|           61|2008-08-01T14:45:37Z|      90|   13|"<p><a href=""htt...|
    |<p>A very good re...| though.</p>"|                null|    null| null|                null|
    +--------------------+-------------+--------------------+--------+-----+--------------------+
    only showing top 2 rows
    

    然而 当我使用熊猫时,它很有魅力。

    df = pd.read_csv('./stacksample/Answers_sample.csv')
    df.head(3) 
    

    输出

    Index Id    OwnerUserId CreationDate    ParentId    Score   Body
    0   92  61  2008-08-01T14:45:37Z    90  13  <p><a href="http://svnbook.red-bean.com/">Vers...
    1   124 26  2008-08-01T16:09:47Z    80  12  <p>I wound up using this. It is a kind of a ha...
    

    我的观察: Apache spark将csv文件中的每一行都视为数据帧的记录(这是合理的),但另一方面,pandas智能地(不确定基于哪些参数)找出记录的实际终点。

    问题 我想知道,如何指示Spark正确加载数据帧。

    要加载的数据如下所示,行以开头 92 和 124 是两个记录。

    Id,OwnerUserId,CreationDate,ParentId,Score,Body
    92,61,2008-08-01T14:45:37Z,90,13,"<p><a href=""http://svnbook.red-bean.com/"">Version Control with Subversion</a></p>
    
    <p>A very good resource for source control in general. Not really TortoiseSVN specific, though.</p>"
    124,26,2008-08-01T16:09:47Z,80,12,"<p>I wound up using this. It is a kind of a hack, but it actually works pretty well. The only thing is you have to be very careful with your semicolons. : D</p>
    
    <pre><code>var strSql:String = stream.readUTFBytes(stream.bytesAvailable);      
    var i:Number = 0;
    var strSqlSplit:Array = strSql.split("";"");
    for (i = 0; i &lt; strSqlSplit.length; i++){
        NonQuery(strSqlSplit[i].toString());
    }
    </code></pre>
    "
    
    2 回复  |  直到 8 年前
        1
  •  13
  •   Jacek Laskowski    8 年前

    我 认为 您应该使用 option("escape", "\"") 看来 " 用作所谓的 quote escape characters 。

    val q = spark.read
      .option("multiLine", true)
      .option("header", true)
      .option("escape", "\"")
      .csv("input.csv")
    scala> q.show
    +---+-----------+--------------------+--------+-----+--------------------+
    | Id|OwnerUserId|        CreationDate|ParentId|Score|                Body|
    +---+-----------+--------------------+--------+-----+--------------------+
    | 92|         61|2008-08-01T14:45:37Z|      90|   13|<p><a href="http:...|
    |124|         26|2008-08-01T16:09:47Z|      80|   12|<p>I wound up usi...|
    +---+-----------+--------------------+--------+-----+--------------------+
    
        2
  •  11
  •   Gaurav Gupta    8 年前

    经过几个小时的斗争,我终于想出了解决办法。

    分析: 数据转储由提供 Stackoverflow 有 quote(") 被另一个逃走了 引号(“”) .由于spark使用 slash(\) 作为转义字符的默认值,我没有传递它,因此它最终会给出无意义的输出。

    更新的代码

    answer_df = sparkSession.read.\
        csv('./stacksample/Answers_sample.csv', 
            inferSchema=True, header=True, multiLine=True, escape='"');
    
    answer_df.show(2)
    

    注意使用 escape 中的参数 csv() 。

    输出

    +---+-----------+-------------------+--------+-----+--------------------+
    | Id|OwnerUserId|       CreationDate|ParentId|Score|                Body|
    +---+-----------+-------------------+--------+-----+--------------------+
    | 92|         61|2008-08-01 20:15:37|      90|   13|<p><a href="http:...|
    |124|         26|2008-08-01 21:39:47|      80|   12|<p>I wound up usi...|
    +---+-----------+-------------------+--------+-----+--------------------+
    

    希望它能帮助其他人,为他们节省一些时间。

    推荐文章