我有一个带有两列的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')]
如何从列内的数据中创建key:value对?
例如:
{
"58542":"MIN",
"58701:"MIN",
etc..
}
出于性能原因,我想避免使用 collect 。我已经尝试了几件事,但似乎无法仅获得值。
答案 0 :(得分:4)
您可以在这里avoid using a udf
使用pyspark.sql.functions.struct
和pyspark.sql.functions.to_json
(Spark 2.1及更高版本):
import pyspark.sql.functions as f
from pyspark.sql import Row
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')
]
df = spark.createDataFrame(data)
df.withColumn("json", f.to_json(f.struct("dma", "zip_code"))).show(truncate=False)
#+---+--------+--------------------------------+
#|dma|zip_code|json |
#+---+--------+--------------------------------+
#|MIN|58542 |{"dma":"MIN","zip_code":"58542"}|
#|MIN|58701 |{"dma":"MIN","zip_code":"58701"}|
#|MIN|57632 |{"dma":"MIN","zip_code":"57632"}|
#|MIN|58734 |{"dma":"MIN","zip_code":"58734"}|
#+---+--------+--------------------------------+
如果您想将zip_code
作为密钥,则可以直接使用pyspark.sql.functions.create_map
创建一个MapType
:
df.withColumn("json", f.create_map(["zip_code", "dma"])).show(truncate=False)
#+---+--------+-----------------+
#|dma|zip_code|json |
#+---+--------+-----------------+
#|MIN|58542 |Map(58542 -> MIN)|
#|MIN|58701 |Map(58701 -> MIN)|
#|MIN|57632 |Map(57632 -> MIN)|
#|MIN|58734 |Map(58734 -> MIN)|
#+---+--------+-----------------+
答案 1 :(得分:2)
正如Ankin所说,您可以为此使用MapType:
df1 = df[['col3', 'col5']]
输出:
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()
答案 2 :(得分:1)
是的,您可以使用
pyspark.sql.types.MapType(keyType, valueType, valueContainsNull=True)
请分享更多信息,例如数据帧示例输出以及您希望作为输出的方式,这将有助于编写相同的代码段。
答案 3 :(得分:1)
还有另一种将数据框转换为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|
+---+--------+
newrdd = data.rdd
keypair_rdd = newrdd.map(lambda x : (x[1],x[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.get('58542')
u'MIN'
答案 4 :(得分:1)
与其他解决方案相比,我不确定性能如何,但是您可以简单地做到这一点:
dict = {row['zipcode']:row['dma'] for row in df.collect()}
print(dict)
#{'58542': 'MIN', '58701': 'MIN', '57632': 'MIN', '58734': 'MIN'}