我有以下格式的df:
+---------------------------------------+
|ID|ESTRUC_COMP |
+---------------------------------------+
|4A|{'AP': '201', 'BQ': '2'} |
|8B| {'AP': '501', 'BQ': '1', 'IN': '5'}|
+---------------------------------------+
我需要这样的东西:
+------------------------------------------------+
|ID|ESTRUC_COMP |AP |BQ|IN|
+------------------------------------------------+
|4A|{'AP': '201', 'BQ': '2'} |201|2 | |
|8B|{'AP': '501', 'BQ': '1', 'IN': '5'}|501|1 |5 |
+------------------------------------------------+
但是,ESTRUC_COMP是一个字符串。
root
|-- ID: string (nullable = true)
|-- ESTRUC_COMP: string (nullable = true)
如何执行此转换?预先谢谢你。
鲍里斯
答案 0 :(得分:1)
由于您使用的是Spark 1.6,因此无法使用pyspark.sql.functions.from_json()
-您将不得不使用@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "invoiceNumber")
private List<InvoiceLineItems> invoiceLineItems;
。
这个问题与PySpark “explode” dict in column非常相似,但是出于两个原因,我承认这不是一个骗子:
您的字符串列不是有效的JSON(由于单引号)
您希望键成为列
不过,第一步是对链接帖子中的相同步骤进行基本调整,并对udf
函数进行较小的调整,该函数将单引号替换为双引号:
parse()
现在您可以解析字符串并调用pyspark.sql.functions.explode()
:
from pyspark.sql.functions import udf, explode, first
from pyspark.sql.types import *
import json
def parse(s):
try:
return json.loads(s.replace("'", '"'))
except json.JSONDecodeError:
pass
parse_udf = udf(parse, MapType(StringType(), StringType()))
最后,pivot()
将键作为列。您可以将df.select("ID", explode(parse_udf("ESTRUC_COMP"))).show()
#+---+---+-----+
#| ID|key|value|
#+---+---+-----+
#| 4A| BQ| 2|
#| 4A| AP| 201|
#| 8B| IN| 5|
#| 8B| BQ| 1|
#| 8B| AP| 501|
#+---+---+-----+
用作聚合函数,因为我们知道每个first()
的键值关系都是一对一的。
ID
当然,由于我定义了df.select("*", explode(parse_udf("ESTRUC_COMP")))\
.groupBy("ID","ESTRUC_COMP").pivot("key").agg(first("value")).show(truncate=False)
#+---+-----------------------------------+---+---+----+
#|ID |ESTRUC_COMP |AP |BQ |IN |
#+---+-----------------------------------+---+---+----+
#|4A |{'AP': '201', 'BQ': '2'} |201|2 |null|
#|8B |{'AP': '501', 'BQ': '1', 'IN': '5'}|501|1 |5 |
#+---+-----------------------------------+---+---+----+
以返回udf
,因此所有结果列都将是字符串。您可以cast
them或相应地修改MapType(StringType(), StringType())
。