Python pyspark从两列中的数据创建字典

Python pyspark从两列中的数据创建字典,python,pyspark,Python,Pyspark,我有一个pyspark数据框,有两列: [Row(zip_code='58542', dma='MIN'), Row(zip_code='58701', dma='MIN'), Row(zip_code='57632', dma='MIN'), Row(zip_code='58734', dma='MIN')] 如何从列中的数据中生成键:值对 e、 g: 出于性能原因,我希望避免使用collect。我尝试了一些方法,但似乎无法获得正确的值。是的,您可以使用 pyspark.sql.typ

我有一个pyspark数据框,有两列:

[Row(zip_code='58542', dma='MIN'),
 Row(zip_code='58701', dma='MIN'),
 Row(zip_code='57632', dma='MIN'),
 Row(zip_code='58734', dma='MIN')]
如何从列中的数据中生成键:值对

e、 g:

出于性能原因,我希望避免使用collect。我尝试了一些方法,但似乎无法获得正确的值。

是的,您可以使用

pyspark.sql.types.MapType(keyType、valueType、valuecontainsnall=True)


请共享更多信息,如dataframe示例输出以及您希望作为输出的方式,这将有助于编写相同的代码段。

正如Ankin所说,您可以为此使用MapType:

import pyspark
from pyspark.sql import Row

sc = pyspark.SparkContext()
spark = pyspark.sql.SparkSession(sc)

data = spark.createDataFrame([Row(zip_code='58542', dma='MIN'),
 Row(zip_code='58701', dma='MIN'),
 Row(zip_code='57632', dma='MIN'),
 Row(zip_code='58734', dma='MIN')])

data.show()
输出:

+---+--------+
|dma|zip_code|
+---+--------+
|MIN|   58542|
|MIN|   58701|
|MIN|   57632|
|MIN|   58734|
+---+--------+


from pyspark.sql.functions import udf
from pyspark.sql import types as T

@udf(T.MapType(T.StringType(), T.StringType()))
def create_struct(zip_code, dma):
    return {zip_code: dma}

data.withColumn('struct', create_struct(data.zip_code, data.dma)).toJSON().collect()
['{"dma":"MIN","zip_code":"58542","struct":{"58542":"MIN"}}',
 '{"dma":"MIN","zip_code":"58701","struct":{"58701":"MIN"}}',
 '{"dma":"MIN","zip_code":"57632","struct":{"57632":"MIN"}}',
 '{"dma":"MIN","zip_code":"58734","struct":{"58734":"MIN"}}']
输出:

+---+--------+
|dma|zip_code|
+---+--------+
|MIN|   58542|
|MIN|   58701|
|MIN|   57632|
|MIN|   58734|
+---+--------+


from pyspark.sql.functions import udf
from pyspark.sql import types as T

@udf(T.MapType(T.StringType(), T.StringType()))
def create_struct(zip_code, dma):
    return {zip_code: dma}

data.withColumn('struct', create_struct(data.zip_code, data.dma)).toJSON().collect()
['{"dma":"MIN","zip_code":"58542","struct":{"58542":"MIN"}}',
 '{"dma":"MIN","zip_code":"58701","struct":{"58701":"MIN"}}',
 '{"dma":"MIN","zip_code":"57632","struct":{"57632":"MIN"}}',
 '{"dma":"MIN","zip_code":"58734","struct":{"58734":"MIN"}}']
您可以在此处使用和(Spark 2.1及以上版本):

导入pyspark.sql.f函数
从pyspark.sql导入行
数据=[
行(邮政编码为58542',dma='MIN'),
行(邮政编码为58701',dma='MIN'),
行(邮政编码为57632',dma为MIN'),
行(邮政编码为58734',dma为分钟)
]
df=spark.createDataFrame(数据)
df.withColumn(“json”,f.to_json(f.struct(“dma”,“邮政编码”))).show(truncate=False)
#+---+--------+--------------------------------+
#|dma |邮政编码| json|
#+---+--------+--------------------------------+
#|MIN | 58542 |{“dma”:“MIN”,“邮政编码”:“58542”}|
#|MIN | 58701 |{“dma”:“MIN”,“邮政编码”:“58701”}|
#|MIN | 57632 |{“dma”:“MIN”,“邮政编码”:“57632”}|
#|MIN | 58734 |{“dma”:“MIN”,“邮政编码”:“58734”}|
#+---+--------+--------------------------------+
如果您希望将
邮政编码
作为键,则可以直接使用以下方法创建
地图类型

df.withColumn(“json”,f.create_-map([“zip_-code”,“dma”])).show(truncate=False)
#+---+--------+-----------------+
#|dma |邮政编码| json|
#+---+--------+-----------------+
#|MIN | 58542 |地图(58542->MIN)|
#|MIN | 58701 |地图(58701->MIN)|
#|MIN | 57632 |地图(57632->MIN)|
#|MIN | 58734 |地图(58734->MIN)|
#+---+--------+-----------------+

还有一种方法可以将数据帧转换为dict。为此,您需要将数据帧转换为键值对rdd,因为它仅适用于键值对rdd。因为字典本身是键值对的组合

data = [
    Row(zip_code='58542', dma='MIN'),
    Row(zip_code='58701', dma='MIN'),
    Row(zip_code='57632', dma='MIN'),
    Row(zip_code='58734', dma='MIN')
]

>>> data.show();
+---+--------+
|dma|zip_code|
+---+--------+
|MIN|   58542|
|MIN|   58701|
|MIN|   57632|
|MIN|   58734|
+---+--------+
将数据帧转换为rdd。 由于您希望zip_代码作为键,dma作为值,因此选择rdd元素“1”作为键,元素“0”作为值。 一旦您有了密钥对rdd,那么只需使用collectAsMap将其转换为一个命令

>>> dict = keypair_rdd.collectAsMap()
>>> print dict
{u'58542': u'MIN', u'57632': u'MIN', u'58734': u'MIN', u'58701': u'MIN'}

>>> dict.keys()
[u'58542', u'57632', u'58734', u'58701']
查找特定键的值:
我不确定这与其他解决方案相比性能如何,但您可以简单地做到:

dict = {row['zipcode']:row['dma'] for row in df.collect()}
print(dict)
#{'58542': 'MIN', '58701': 'MIN', '57632': 'MIN', '58734': 'MIN'}

创建地图不需要
udf
>>> dict.get('58542')
u'MIN'
dict = {row['zipcode']:row['dma'] for row in df.collect()}
print(dict)
#{'58542': 'MIN', '58701': 'MIN', '57632': 'MIN', '58734': 'MIN'}