Pyspark 如何在spark中使用多个分隔符保存文件

Pyspark 如何在spark中使用多个分隔符保存文件,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我需要保存一个由|个字符分隔的文件,但执行下面的命令时出错。我可以在Spark中使用多个分隔符保存文件吗 mydf1.coalesce(1).write.option("compression","none").format("csv").mode("Overwrite").option("delimiter","|~").save("my_hdfs_path") // Error : pyspark.sql.utils.IllegalArgumentException: u'Delimite

我需要保存一个由|个字符分隔的文件,但执行下面的命令时出错。我可以在Spark中使用多个分隔符保存文件吗

mydf1.coalesce(1).write.option("compression","none").format("csv").mode("Overwrite").option("delimiter","|~").save("my_hdfs_path")

// Error : pyspark.sql.utils.IllegalArgumentException: u'Delimiter cannot be more than one character: |~'

好吧,我们仍在等待正式的解决方案,因为这个问题仍然悬而未决,而且仍然依赖政府。在univocity CSV设置中,CSV分隔符只能是单个字符,这将约束解析器读取器和生成器编写器

变通办法

很难找到一种通用、快速、安全的CSV写入方式。但这取决于您的数据大小和CSV内容日期格式的复杂性?通货引用?,我们可以找到一条捷径。以下是一些令人鼓舞的想法

使用特殊字符say写入CSV⊢ 然后替换为|~

还没有进行基准测试,但在我看来,它很有希望成为最快的

df.coalesce(1).write.option("compression","none").option("delimiter", "⊢").mode("overwrite").csv("raw-output")
然后用理想的本地方法进行后期处理,比如sed

在PySpark中,将每一行连接到一个字符串,然后作为文本文件写入

能够灵活地处理本地和特殊需求-需要更多的工作

d=[{'name':'Alice','age':1},{'name':'Bob','age':3}] df=spark.createDataFramed,名称:string,年龄:int df.show +---+--+ |姓名|年龄| +---+--+ |爱丽丝| 1| |鲍勃| 3| +---+--+ @自由民主党 def mkstrname,年龄: 例如,字符串字段{name}应该用`` 返回“{name}| ~{age}”。formatname=name,age=age 将CSV行重新解析为字符串 df_unparsed=df.selectmkstrname,age.aliascsv_行 df_未经分析的节目 +-----+ |csv_行| +-----+ |爱丽丝| ~1| |鲍勃| ~3| +-----+ df_unparsed.coalesce1.write.optioncompression,none.modeoverwrite.textoutput savetxt允许多个字符作为分隔符,因此

如果你关心浮点数的精确性,numpy有很多内置功能

import pandas as pd
import numpy as np

# convert `Spark.DataFrame` to `Pandas.DataFrame`
df_pd = df.toPandas()

# use `numpy.savetxt` to save `Pandas.DataFrame`
np.savetxt("a-long-day.csv", df_pd, delimiter="|~", fmt="%s")

从Spark 3.0开始,我们没有这个问题,但如果使用以前的版本>Spark 2.3,这也可以用作解决方案。基本上是连接所有列并用空格填充null,然后使用所需的分隔符和标题写入数据。这将是比硬编码更通用的解决方案。这允许保留标题

    from pyspark.sql.functions import *
    from pyspark.sql import functions as F
    target_row_delimited = "|,"
    df=df.select([col(c).cast("string") for c in df.columns])
    df=df.na.fill("")
    headername=target_row_delimited.join(df.columns)
    df=df.withColumn(headername, concat_ws(target_row_delimited, *df.columns))
    df.select(df[headername].write.format("csv").mode(modeval).option("quoteAll", "false").option("quote","\u0000").option("header", "true").save(tgt_path + "/")
如果我们需要使用多个分隔符进行读取,可以使用以下解决方案

source_delimiter = "|_|"
headcal = spark.read.text(source_filename)
headers = headcal.take(1)[0]['value']
header_column = headers.split(source_delimiter)
df = sc.textFile(source_filename).map(lambda x: x.split(source_delimiter)).toDF(header_column)
source_delimiter = "|_|"
headcal = spark.read.text(source_filename)
headers = headcal.take(1)[0]['value']
header_column = headers.split(source_delimiter)
df = sc.textFile(source_filename).map(lambda x: x.split(source_delimiter)).toDF(header_column)