展开PySpark DataFrame的数组列

时间:2019-05-17 11:38:48

标签: python dataframe pyspark graphframes

我必须使用以下数据将DataFrame转换为GraphFrame。让我们考虑一个数据帧中的Authors列,其中包含一个字符串数组,如下所示:

+-----------+------------------------------------+
|ArticlePMID|               Authors              |
+-----------+------------------------------------+
|    PMID1  |['Author 1', 'Author 2', 'Author 3']|
|    PMID2  |['Author 4', 'Author 5']            |
+-----------+------------------------------------+

在数据表中,我们列出了在同一篇论文上一起合作的作者。现在,我想将第二列扩展为包含以下结构的新数据框:

+---------------+---------------+ 
| Collaborator1 | Collaborator2 |
+---------------+---------------+ 
| 'Author 1'    | 'Author 2'    |
| 'Author 1'    | 'Author 3'    |
| 'Author 2'    | 'Author 3'    |
| 'Author 4'    | 'Author 5'    |
+---------------+---------------+

我尝试使用explode函数,但是那样只能将数组扩展为单个作者列,而我失去了协作网络。

能不能告诉我如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

只要您使用的是pyspark 2.1版或更高版本,就可以使用posexplode后跟join

首先爆炸,其位置为数组:

from pyspark.sql.functions import posexplode
exploded = df.select("*", posexplode("Authors").alias("pos", "Author"))
exploded.show()
#+-----------+--------------------+---+--------+
#|ArticlePMID|             Authors|pos|  Author|
#+-----------+--------------------+---+--------+
#|      PMID1|[Author 1, Author...|  0|Author 1|
#|      PMID1|[Author 1, Author...|  1|Author 2|
#|      PMID1|[Author 1, Author...|  2|Author 3|
#|      PMID2|[Author 4, Author 5]|  0|Author 4|
#|      PMID2|[Author 4, Author 5]|  1|Author 5|
#+-----------+--------------------+---+--------+

现在在ArticlePMID列上将爆炸的DataFrame与其自身相连,并仅选择左侧表的pos小于右侧表的列。

exploded.alias("l").join(exploded.alias("r"), on="ArticlePMID", how="inner")\
    .where("l.pos < r.pos")\
    .selectExpr("l.Author AS Collaborator1", "r.Author AS Collaborator2")\
    .show()
#+-------------+-------------+
#|Collaborator1|Collaborator2|
#+-------------+-------------+
#|     Author 1|     Author 2|
#|     Author 1|     Author 3|
#|     Author 2|     Author 3|
#|     Author 4|     Author 5|
#+-------------+-------------+

使用pos进行过滤是为了避免同时列出两种相同的作者对。