Python PySpark-重命名JSON中存储为CSV文件中字符串列的键名

Python PySpark-重命名JSON中存储为CSV文件中字符串列的键名,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,我想更新json中存储为字符串列的键名,并将其保存回字符串类型列。我正在从我的csv中读取这些列,并将其存储为csv 这就是我的输入csv的外观 candidate_email,transactions cust2@email.com,"[{'transaction_id':'12', 'transaction_amount':'$23.43'},{'transaction_id':'15', 'transaction_amount':'$723.41'}]" cust1@email.com,"

我想更新json中存储为字符串列的键名,并将其保存回字符串类型列。我正在从我的csv中读取这些列,并将其存储为csv

这就是我的输入csv的外观

candidate_email,transactions
cust2@email.com,"[{'transaction_id':'12', 'transaction_amount':'$23.43'},{'transaction_id':'15', 'transaction_amount':'$723.41'}]"
cust1@email.com,"[{'transaction_id':'10', 'transaction_amount':'$55.99'},{'transaction_id':'11', 'transaction_amount':'$20.46'},{'transaction_id':'13', 'transaction_amount':'$5.89'},{'transaction_id':'14', 'transaction_amount':'$35.61'}]"
我想在我的json中用
id
替换
transaction\u id
键,用
amount
替换
transaction\u amount
,并将其保存为csv

input_df = spark.read.csv('transactions/*.csv', header='true', inferSchema = True)
input_df.printSchema()
# root
#  |-- candidate_email: string (nullable = true)
#  |-- transactions: string (nullable = true)

input_df.show(10, False)
# +-----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
# |candidate_email|transactions                                                                                                                                                                                                                |
# +-----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
# |cust2@email.com        |[{'transaction_id':'12', 'transaction_amount':'$23.43'},{'transaction_id':'15', 'transaction_amount':'$723.41'}]                                                                                                            |
# |cust1@email.com        |[{'transaction_id':'10', 'transaction_amount':'$55.99'},{'transaction_id':'11', 'transaction_amount':'$20.46'},{'transaction_id':'13', 'transaction_amount':'$5.89'},{'transaction_id':'14', 'transaction_amount':'$35.61'}]|
# +-----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
如何替换密钥以获得以下输出

output_df.show(10,False)
# +---------------+----------------------------------------------------------------------------------------------------------------------------+
# |candidate_email|transactions                                                                                                                |
# +---------------+----------------------------------------------------------------------------------------------------------------------------+
# |cust1@email.com|[{'id':'10', 'amount':'$55.99'},{'id':'11', 'amount':'$20.46'},{'id':'13', 'amount':'$5.89'},{'id':'14', 'amount':'$35.61'}]|
# |cust2@email.com|[{'id':'12', 'amount':'$23.43'},{'id':'15', 'amount':'$723.41'}]                                                            |
# +---------------+----------------------------------------------------------------------------------------------------------------------------+
注意:两列都是字符串类型的列

output_df.printSchema()
# root
#  |-- candidate_email: string (nullable = true)
#  |-- transactions: string (nullable = true)

从_json使用
将事务列读取为
数组(结构…
),然后转换为所需的字段名

  • 然后
    explode+到_json+groupBy+collect_list
    获取所需的json
示例:

df.show()
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|candidate_email|transactions                                                                                                    |
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|cust2@email.com|[{'transaction_id':'12', 'transaction_amount':'$23.43'},{'transaction_id':'15', 'transaction_amount':'$723.41'}]|
#+---------------+----------------------------------------------------------------------------------------------------------------+

st=ArrayType(StructType([StructField("transaction_id", StringType()),StructField("transaction_amount", StringType())]))

df.withColumn("jsn",from_json(col("transactions"),st).cast("array<struct<id:string,amount:string>>")).\
selectExpr("*","explode(jsn)").\
select("*","col.*").\
drop(*drop_cols).\
selectExpr("candidate_email","to_json(struct(id,amount)) as trans").\
groupBy("candidate_email").\
agg(collect_list("trans").alias("transactions")).\
show(10,False)

#+---------------+---------------------------------------------------------------+
#|candidate_email|transactions                                                   |
#+---------------+---------------------------------------------------------------+
#|cust2@email.com|[{"id":"12","amount":"$23.43"}, {"id":"15","amount":"$723.41"}]|
#+---------------+---------------------------------------------------------------+
df.show()
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|候选人|电子邮件|交易|
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|cust2@email.com|[{'transaction\u id':'12','transaction\u amount':'23.43'},{'transaction\u id':'15','transaction\u amount':'723.41'}]|
#+---------------+----------------------------------------------------------------------------------------------------------------+
st=ArrayType(StructType([StructField(“交易\ id”,StringType()),StructField(“交易\金额”,StringType())]))
df.withColumn(“jsn”,来自_json(col(“transactions”),st.cast(“array”))\
选择EXPR(“*”,“分解(jsn)”)\
选择(“*”,“列*”)\
下降(*下降)\
选择EXPR(“候选人电子邮件”、“发送至json(结构(id,金额))作为trans”)\
groupBy(“候选人电子邮件”)\
agg(收款清单(“交易”)。别名(“交易”)\
显示(10,假)
#+---------------+---------------------------------------------------------------+
#|候选人|电子邮件|交易|
#+---------------+---------------------------------------------------------------+
#|cust2@email.com|[{“id”:“12”,“金额”:“$23.43”},{“id”:“15”,“金额”:“$723.41”}]|
#+---------------+---------------------------------------------------------------+

使用来自_json的
将事务列读取为
数组(结构…
),然后转换为所需的字段名

  • 然后
    explode+到_json+groupBy+collect_list
    获取所需的json
示例:

df.show()
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|candidate_email|transactions                                                                                                    |
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|cust2@email.com|[{'transaction_id':'12', 'transaction_amount':'$23.43'},{'transaction_id':'15', 'transaction_amount':'$723.41'}]|
#+---------------+----------------------------------------------------------------------------------------------------------------+

st=ArrayType(StructType([StructField("transaction_id", StringType()),StructField("transaction_amount", StringType())]))

df.withColumn("jsn",from_json(col("transactions"),st).cast("array<struct<id:string,amount:string>>")).\
selectExpr("*","explode(jsn)").\
select("*","col.*").\
drop(*drop_cols).\
selectExpr("candidate_email","to_json(struct(id,amount)) as trans").\
groupBy("candidate_email").\
agg(collect_list("trans").alias("transactions")).\
show(10,False)

#+---------------+---------------------------------------------------------------+
#|candidate_email|transactions                                                   |
#+---------------+---------------------------------------------------------------+
#|cust2@email.com|[{"id":"12","amount":"$23.43"}, {"id":"15","amount":"$723.41"}]|
#+---------------+---------------------------------------------------------------+
df.show()
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|候选人|电子邮件|交易|
#+---------------+----------------------------------------------------------------------------------------------------------------+
#|cust2@email.com|[{'transaction\u id':'12','transaction\u amount':'23.43'},{'transaction\u id':'15','transaction\u amount':'723.41'}]|
#+---------------+----------------------------------------------------------------------------------------------------------------+
st=ArrayType(StructType([StructField(“交易\ id”,StringType()),StructField(“交易\金额”,StringType())]))
df.withColumn(“jsn”,来自_json(col(“transactions”),st.cast(“array”))\
选择EXPR(“*”,“分解(jsn)”)\
选择(“*”,“列*”)\
下降(*下降)\
选择EXPR(“候选人电子邮件”、“发送至json(结构(id,金额))作为trans”)\
groupBy(“候选人电子邮件”)\
agg(收款清单(“交易”)。别名(“交易”)\
显示(10,假)
#+---------------+---------------------------------------------------------------+
#|候选人|电子邮件|交易|
#+---------------+---------------------------------------------------------------+
#|cust2@email.com|[{“id”:“12”,“金额”:“$23.43”},{“id”:“15”,“金额”:“$723.41”}]|
#+---------------+---------------------------------------------------------------+

为什么不直接做regexp\u replace:
df.withColumn(“transactions”,regexp\u replace(“transactions”,“transaction”,“”)).show()
你是对的,但我正在考虑使用UDF,在这里我可以使用json python模块对键对做更多的事情。此外,regex将替换出现的每一个
事务
,但我想用唯一的名称更改一些特定的键。另一种方法是使用from_json+到_json来更改键名,以防原始名称和预期名称之间没有显式模式。为什么不直接使用regexp_替换:
df.withColumn(“事务”),regexp_replace(“transactions”,“transaction_u”,”)。show()
你说得对,但我正在考虑使用UDF,通过它我可以使用json python模块对密钥对做更多的事情。此外,regex将替换每次出现的
事务
,但我想用唯一的名称更改一些特定的键。另一种方法是使用从_json+到_json来更改键名,以防原始名称和预期名称之间没有显式模式。