我有一个数据框,有一行和几列.一些列是单个值,其他列是列表.所有列表列的长度都相同.我想将每个列表列拆分为一个单独的行,同时保持任何非列表列不变.
样本DF:
from pyspark import Row
from pyspark.sql import SQLContext
from pyspark.sql.functions import explode
sqlc = SQLContext(sc)
df = sqlc.createDataFrame([Row(a=1, b=[1,2,3],c=[7,8,9], d='foo')])
# +---+---------+---------+---+
# | a| b| c| d|
# +---+---------+---------+---+
# | 1|[1, 2, 3]|[7, 8, 9]|foo|
# +---+---------+---------+---+
Run Code Online (Sandbox Code Playgroud)
我想要的是:
+---+---+----+------+
| a| b| c | d |
+---+---+----+------+
| 1| 1| 7 | foo |
| 1| 2| 8 | foo |
| 1| 3| 9 | foo |
+---+---+----+------+
Run Code Online (Sandbox Code Playgroud)
如果我只有一个列表列,只需执行以下操作即可explode:
df_exploded = df.withColumn('b', explode('b')) …Run Code Online (Sandbox Code Playgroud) 考虑以下DataFrame:
+------+-----------------------+
|type |names |
+------+-----------------------+
|person|[john, sam, jane] |
|pet |[whiskers, rover, fido]|
+------+-----------------------+
Run Code Online (Sandbox Code Playgroud)
可以使用以下代码创建:
import pyspark.sql.functions as f
data = [
('person', ['john', 'sam', 'jane']),
('pet', ['whiskers', 'rover', 'fido'])
]
df = sqlCtx.createDataFrame(data, ["type", "names"])
df.show(truncate=False)
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以通过对每个元素应用函数而不使用?来直接修改ArrayType()列?"names"udf
例如,假设我想将该函数foo应用于"names"列。(我将使用其中的例子foo是str.upper只用于说明目的,但我的问题是关于可以应用到一个可迭代的元素任何有效的功能。)
foo = lambda x: x.upper() # defining it as str.upper as an example
df.withColumn('X', [foo(x) for x in f.col("names")]).show()
Run Code Online (Sandbox Code Playgroud)
TypeError:列不可迭代
我可以使用udf:
foo_udf = f.udf(lambda row: [foo(x) …Run Code Online (Sandbox Code Playgroud) 这是关于transform高阶函数(https://issues.apache.org/jira/browse/SPARK-23908).
有没有办法将它用作标准功能(在包中org.apache.spark.sql.functions._)?
我有一个字符串数组,我想对每个字符串应用URI规范化.现在我用UDF做了.我刚刚用spark 2.4.0跳过它,我可以跳过UDF.
当我看到它应该使用selectExpr类似df.selectExpr("transform(i, x -> x + 1)"),但它只是为了与使用selectExpr?
无论如何使用它来提供转换的自定义功能?有没有办法实现它,还是应该使用好的旧UDF?