如何将PySpark中的表数据框导出到CSV?


79

我正在使用Spark 1.3.1(PySpark),并且已经使用SQL查询生成了一个表。我现在有一个对象是DataFrame。我想将此DataFrame对象(我称其为“表”)导出到一个csv文件,以便我可以操纵它并绘制列。如何将DataFrame“表格”导出到csv文件?

谢谢!

Answers:


187

如果数据帧适合驱动程序内存,并且您想保存到本地文件系统,则可以使用方法将Spark DataFrame转换为本地Pandas DataFrametoPandas,然后简单地使用to_csv

df.toPandas().to_csv('mycsv.csv')

否则,您可以使用spark-csv

  • 火花1.3

    df.save('mycsv.csv', 'com.databricks.spark.csv')
    
  • 火花1.4+

    df.write.format('com.databricks.spark.csv').save('mycsv.csv')
    

在Spark 2.0+中,您可以csv直接使用数据源:

df.write.csv('mycsv.csv')

超级答案。对于第一种选择,如果我要写入以竖线分隔的文件,而不是逗号分隔的CSV,这可能吗?
布赖恩·沃特斯

7
如果您有spark数据帧,则可以使用df.write.csv('/tmp/lookatme/'),这将删除“/tmp/lookatme使用spark”中的一组csv文件,比在熊猫中序列化它要快得多。唯一的缺点是,最终将得到一组csvs而不是单个csvs,并且如果目标工具不知道如何串联它们,则需要您自己进行操作。
Txangel

1
使csv脱颖而出是一件大事。关于第一个解决方案的有趣之处在于,to_csv无需导入Pandas即可运行。.toPandas是Spark的一部分,也许隐式导入了它
。– cardamom

23
df.coalesce(1).write.csv('mycsv.csv')如果您坚持只使用一个输出文件,则应该可以使用
MichaelChirico '18

1
@Txangel感谢您的回答。但是,当我使用它运行时没有任何错误,但是我找不到在目标位置创建的任何csv。有什么想法吗?
Rotail

34

对于Apache Spark 2+,为了将数据帧保存到单个csv文件中。使用以下命令

query.repartition(1).write.csv("cc_out.csv", sep='|')

在这里1表明我只需要一个csv分区。您可以根据需要进行更改。


6
如此处所示:spark.apache.org/docs/2.2.0/api/python/…建议使用Coalesce()而不是repartition()来提高性能(“如果要减少此RDD中的分区数,请考虑使用合并,以避免合并。”)
Seastar

@Seastar:虽然合并在某些用例中可能有优势,但是您的评论不适用于这种特殊情况。如果您要在HDFS(或其他任何文件)中包含.csv,通常会希望在整个群集中散布一个文件,而不是散布数十个文件(整个过程repartition(1)。您需要通过这两种方式对数据进行混洗,合并对整体没有帮助
。– Markus

19

如果无法使用spark-csv,则可以执行以下操作:

df.rdd.map(lambda x: ",".join(map(str, x))).coalesce(1).saveAsTextFile("file.csv")

如果您需要使用换行符或逗号来处理字符串,将无法正常工作。用这个:

import csv
import cStringIO

def row2csv(row):
    buffer = cStringIO.StringIO()
    writer = csv.writer(buffer)
    writer.writerow([str(s).encode("utf-8") for s in row])
    buffer.seek(0)
    return buffer.read().strip()

df.rdd.map(row2csv).coalesce(1).saveAsTextFile("file.csv")

7

您需要将Dataframe重新划分为一个分区,然后以Unix文件系统格式定义文件的格式,路径和其他参数,然后就可以开始了,

df.repartition(1).write.format('com.databricks.spark.csv').save("/path/to/file/myfile.csv",header = 'true')

阅读有关重新分区功能的 更多信息阅读有关保存功能的更多信息

但是,重新分区是一项代价高昂的函数,并且toPandas()最糟糕。尝试在以前的语法中使用.coalesce(1)代替.repartition(1)以获得更好的性能。

阅读有关分区功能与合并功能的更多信息


3

怎么样(如果你不想一个班轮)?

for row in df.collect():
    d = row.asDict()
    s = "%d\t%s\t%s\n" % (d["int_column"], d["string_column"], d["string_column"])
    f.write(s)

f是打开的文件描述符。分隔符也是TAB字符,但是很容易更改为所需的任何字符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.