如何从pyspark Dataframe 中输出csv文件和XML文件,其中多个列具有相同的名称?

tv6aics1  于 2023-07-31  发布在  Spark
关注(0)|答案(2)|浏览(138)

我有一个像下面这样的spark dataframe:
| value_1| value_2| value_3|值_4| value_4 |
| --|--|--|--| ------------ |
| abcd123| efgh456|联系我们|mnop012| mnop012 |
我需要将这个dataframe从databricks和XML文件转换为csv文件,以便所有列名都相同,如下所示。
| 价值|价值|价值|价值| value |
| --|--|--|--| ------------ |
| abcd123| efgh456|联系我们|mnop012| mnop012 |
也许我可以通过将数据类型分别更改为String,Char,Varchar来输出3个同名的列。但现在有四列。
这是一个xml示例:

<actions>
    <action>
      <action_type>create</action_type>
      <profile>
        <ID>1</ID>
        <value>abcd123</value>
        <value>efgh456</value>
        <value>ijkl789</value>
        <value>mnop012</value>
      </profile>
    </action>
</actions>

字符串

epggiuax

epggiuax1#

默认情况下,spark不允许创建csv file with duplicate column names
但是我们可以为这种情况做一个变通方案,在数据中引入所需的列名作为一个新行,然后写为csv文件**without header**。

Example:

df = spark.createDataFrame([[1, 2, 3,4,5]], ['id','value_1','value_2','value_3','value_4'])

#header line as data
df1 = spark.createDataFrame([['id','value','value','value','value']])

#union all the data and write as csv
df1.unionAll(df).repartition(1).write.\
mode("overwrite").option("header",False).\
csv("<path_to_dir>")

字符串

Print the file contents:

print(dbutils.fs.head("<path_to_dir>"))
#id,value,value,value,value
#1,2,3,4,5

wvyml7n5

wvyml7n52#

我不知道PySpark/Spark,所以我只能建议你直接从spark dataframe转换为中间CSV,然后使用普通Python将其转换为你需要的CSV和XML。
假设你可以得到一个input.csv,比如(使用df.write.csv(...)):

ID,value_1,value_2,value_3,value_4
1,abcd123,efgh456,ijkl789,mnop012

字符串
读取CSV并将行保存到列表中(如果存在,则丢弃标题):

import csv

with open("input.csv", newline="", encoding="utf-8") as f:
    reader = csv.reader(f)
    next(reader)  # discard header
    rows = list(reader)


然后用正确的标题写回行:

with open("output.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["ID"] + ["value"] * len(rows[0][1:]))
    writer.writerows(rows)


这给了我:

ID,value,value,value,value
1,abcd123,efgh456,ijkl789,mnop012


假设第一列是您的ID,那么它只是在ID之后的输入中每隔一列写入一个“value”列。
Python的xml.etree.ElementTree将再次使用行列表构建您需要的XML,从自顶向下开始,从根“actions”元素开始:

import xml.etree.ElementTree as ET

root = ET.Element("actions")
for row in rows:
    action = ET.SubElement(root, "action")

    action_type = ET.SubElement(action, "action_type")
    action_type.text = "create"

    profile = ET.SubElement(action, "profile")

    id_ = ET.SubElement(profile, "id")
    id_.text = row[0]

    for x in row[1:]:
        value = ET.SubElement(profile, "value")
        value.text = x

tree = ET.ElementTree(root)
ET.indent(tree)
tree.write("output.xml")


同样,它假设第一列是ID,后面的每一列都应该是“value”。这给了我:

<actions>
  <action>
    <action_type>create</action_type>
    <profile>
      <id>1</id>
      <value>abcd123</value>
      <value>efgh456</value>
      <value>ijkl789</value>
      <value>mnop012</value>
    </profile>
  </action>
</actions>

相关问题