PySpark:嵌套-将一列拆分为多个新列
PySpark: nested-splitting one column into multiple new ones
我在 Hadoop 上有一个 network.log
:
{"Source":"Network","Detail":"Event=01|Device=Mobile|ClientIP=10.0.0.0|URL=example.com"}
我想将其加载为拆分 Detail
与 |
的数据帧。然后我想使用 =
进一步拆分每个新列,左侧部分作为列名,右侧部分作为值。
预期结果为:
Source | Event | Device | ClientIP | URL
Network | 01 | Mobile | 10.0.0.0 | example.com
我做了第一次拆分如下:
from pyspark import SparkContext
from pyspark.sql import functions, SQLContext
INPUT_PATH = 'network.log'
sc = SparkContext("local", "NetworkEvent")
sqlContext = SQLContext(sc)
raw = sqlContext.read.json(INPUT_PATH)
detail_col = functions.split(raw['Detail'], '\|')
for i in range(4):
raw = raw.withColumn('col_' + str(i), detail_col.getItem(i))
raw.show()
我的问题是,我可以在 detail_col.getItem(i)
的基础上同时进行第二次拆分吗?我可以考虑为新数据框的每一列创建另一个 UDF,但是在一个 UDF 中有更优雅的方法吗?非常感谢!
注意:我使用的是 Spark 1.5.0,因此 Pandas' UDF 将不可用。
在1.5.0中,您可以使用regexp_extract
。
from pyspark.sql import functions as F
for i in ['Event', 'Device', 'ClientIP', 'URL']:
df = df.withColumn(i, F.regexp_extract('Detail',"{}=([^\|]+)".format(i),1))
df.show()
+-------+--------------------+-----+------+--------+-----------+
| Source| Detail|Event|Device|ClientIP| URL|
+-------+--------------------+-----+------+--------+-----------+
|Network|Event=01|Device=M...| 01|Mobile|10.0.0.0|example.com|
+-------+--------------------+-----+------+--------+-----------+
无需为此编写 UDF,您可以应用多种替代方案来实现此目的,这是其中一种替代方案:-
from pyspark import SparkContext
from pyspark.sql import functions
INPUT_PATH = 'network.log'
sc = SparkContext("local", "NetworkEvent")
sqlContext = SQLContext(sc)
raw = sqlContext.read.json(INPUT_PATH)
detail_col = functions.split(raw['Detail'], '\|')
cols_to_be = raw.select([functions.split(detail_col.getItem(i), "=").getItem(0).alias("col_"+str(i)) for i in range(4)]).first()
for i in range(4):
raw = raw.withColumn(
cols_to_be["col_"+str(i)],
functions.split(detail_col.getItem(i), "=").getItem(1)
)
raw.show()
+--------------------+-------+-----+------+--------+-----------+
| Detail| Source|Event|Device|ClientIP| URL|
+--------------------+-------+-----+------+--------+-----------+
|Event=01|Device=M...|Network| 01|Mobile|10.0.0.0|example.com|
+--------------------+-------+-----+------+--------+-----------+
希望您的详细信息数据应遵循某种模式。
我在 Hadoop 上有一个 network.log
:
{"Source":"Network","Detail":"Event=01|Device=Mobile|ClientIP=10.0.0.0|URL=example.com"}
我想将其加载为拆分 Detail
与 |
的数据帧。然后我想使用 =
进一步拆分每个新列,左侧部分作为列名,右侧部分作为值。
预期结果为:
Source | Event | Device | ClientIP | URL
Network | 01 | Mobile | 10.0.0.0 | example.com
我做了第一次拆分如下:
from pyspark import SparkContext
from pyspark.sql import functions, SQLContext
INPUT_PATH = 'network.log'
sc = SparkContext("local", "NetworkEvent")
sqlContext = SQLContext(sc)
raw = sqlContext.read.json(INPUT_PATH)
detail_col = functions.split(raw['Detail'], '\|')
for i in range(4):
raw = raw.withColumn('col_' + str(i), detail_col.getItem(i))
raw.show()
我的问题是,我可以在 detail_col.getItem(i)
的基础上同时进行第二次拆分吗?我可以考虑为新数据框的每一列创建另一个 UDF,但是在一个 UDF 中有更优雅的方法吗?非常感谢!
注意:我使用的是 Spark 1.5.0,因此 Pandas' UDF 将不可用。
在1.5.0中,您可以使用regexp_extract
。
from pyspark.sql import functions as F
for i in ['Event', 'Device', 'ClientIP', 'URL']:
df = df.withColumn(i, F.regexp_extract('Detail',"{}=([^\|]+)".format(i),1))
df.show()
+-------+--------------------+-----+------+--------+-----------+
| Source| Detail|Event|Device|ClientIP| URL|
+-------+--------------------+-----+------+--------+-----------+
|Network|Event=01|Device=M...| 01|Mobile|10.0.0.0|example.com|
+-------+--------------------+-----+------+--------+-----------+
无需为此编写 UDF,您可以应用多种替代方案来实现此目的,这是其中一种替代方案:-
from pyspark import SparkContext
from pyspark.sql import functions
INPUT_PATH = 'network.log'
sc = SparkContext("local", "NetworkEvent")
sqlContext = SQLContext(sc)
raw = sqlContext.read.json(INPUT_PATH)
detail_col = functions.split(raw['Detail'], '\|')
cols_to_be = raw.select([functions.split(detail_col.getItem(i), "=").getItem(0).alias("col_"+str(i)) for i in range(4)]).first()
for i in range(4):
raw = raw.withColumn(
cols_to_be["col_"+str(i)],
functions.split(detail_col.getItem(i), "=").getItem(1)
)
raw.show()
+--------------------+-------+-----+------+--------+-----------+
| Detail| Source|Event|Device|ClientIP| URL|
+--------------------+-------+-----+------+--------+-----------+
|Event=01|Device=M...|Network| 01|Mobile|10.0.0.0|example.com|
+--------------------+-------+-----+------+--------+-----------+
希望您的详细信息数据应遵循某种模式。