Python 2.7 使用柱替换柱上的PySPARK UDF
写入此UDF是为了用变量替换列的值。Python 2.7;Spark 2.2.0Python 2.7 使用柱替换柱上的PySPARK UDF,python-2.7,pyspark,pyspark-dataframes,Python 2.7,Pyspark,Pyspark Dataframes,写入此UDF是为了用变量替换列的值。Python 2.7;Spark 2.2.0 import pyspark.sql.functions as func def updateCol(col, st): return func.expr(col).replace(func.expr(col), func.expr(st)) updateColUDF = func.udf(updateCol, StringType()) 变量L_1到L_3为每行更新了列。 我这样称
import pyspark.sql.functions as func
def updateCol(col, st):
return func.expr(col).replace(func.expr(col), func.expr(st))
updateColUDF = func.udf(updateCol, StringType())
变量L_1到L_3为每行更新了列。
我这样称呼它:
updatedDF = orig_df.withColumn("L1", updateColUDF("L1", func.format_string(L_1))). \
withColumn("L2", updateColUDF("L2", func.format_string(L_2))). \
withColumn("L3", updateColUDF("L3",
withColumn("NAME", func.format_string(name)). \
withColumn("AGE", func.format_string(age)). \
select("id", "ts", "L1", "L2", "L3",
"NAME", "AGE")
错误是:
return Column(sc._jvm.functions.expr(str))
AttributeError: 'NoneType' object has no attribute '_jvm'
尝试创建一个示例数据帧,然后使用PySpark中的
lit
函数
似乎工作正常,这是使用Databricks笔记本
错误是因为您正在udf中使用pyspark函数。了解母语、二语的内容也会很有帮助。。变量 但是,如果我正确理解了您想要做的事情,那么您不需要自定义项。我假设L1,L2等都是常数,对吗?如果没有,请让我知道相应地调整代码。下面是一个例子:
from pyspark import SparkConf
from pyspark.sql import SparkSession, functions as F
conf = SparkConf()
spark_session = SparkSession.builder \
.config(conf=conf) \
.appName('test') \
.getOrCreate()
data = [{'L1': "test", 'L2': "data"}, {'L1': "other test", 'L2': "other data"}]
df = spark_session.createDataFrame(data)
df.show()
# +----------+----------+
# | L1| L2|
# +----------+----------+
# | test| data|
# |other test|other data|
# +----------+----------+
L1 = 'some other data'
updatedDF = df.withColumn(
"L1",
F.lit(L1)
)
updatedDF.show()
# +---------------+----------+
# | L1| L2|
# +---------------+----------+
# |some other data| data|
# |some other data|other data|
# +---------------+----------+
# or if you need to replace the value in a more complex way
pattern = '\w+'
updatedDF = updatedDF.withColumn(
"L1",
F.regexp_replace(F.col("L1"), pattern, "testing replace")
)
updatedDF.show()
# +--------------------+----------+
# | L1| L2|
# +--------------------+----------+
# |testing replace t...| data|
# |testing replace t...|other data|
# +--------------------+----------+
# or even something more complicated:
# set L1 value to L2 column when L2 column equals to data, otherwise, just leave L2 as it is
updatedDF = df.withColumn(
"L2",
F.when(F.col('L2') == 'data', L1).otherwise(F.col('L2'))
)
updatedDF.show()
# +----------+---------------+
# | L1| L2|
# +----------+---------------+
# | test|some other data|
# |other test| other data|
# +----------+---------------+
你的例子是:
DF = orig_df.withColumn("L1", pyspark_func.lit(L_1))
...
此外,请确保在这一点之前有一个活动的spark会话
我希望这有帮助
编辑:如果L1、L2等是列表,那么一个选项是使用它们创建一个数据帧并连接到初始df。不幸的是,我们需要索引进行连接,因为您的数据帧非常大,我认为这不是一个非常有效的解决方案。我们也可以使用广播和udf,或者广播和加入
下面是一个(我认为是次优的)如何进行连接的示例:
L1 = ['row 1 L1', 'row 2 L1']
L2 = ['row 1 L2', 'row 2 L2']
# create a df with indexes
to_update_df = spark_session.createDataFrame([{"row_index": i, "L1": row[0], "L2": row[1]} for i, row in enumerate(zip(L1, L2))])
# add indexes to the initial df
indexed_df = updatedDF.rdd.zipWithIndex().toDF()
indexed_df.show()
# +--------------------+---+
# | _1 | _2 |
# +--------------------+---+
# | [test, some other... | 0 |
# | [other test, othe... | 1 |
# +--------------------+---+
# bring the df back to its initial form
indexed_df = indexed_df.withColumn('row_number', F.col("_2"))\
.withColumn('L1', F.col("_1").getItem('L1'))\
.withColumn('L2', F.col("_1").getItem('L2')).\
select('row_number', 'L1', 'L2')
indexed_df.show()
# +----------+----------+---------------+
# |row_number| L1| L2|
# +----------+----------+---------------+
# | 0| test|some other data|
# | 1|other test| other data|
# +----------+----------+---------------+
# join with your results and keep the updated columns
final_df = indexed_df.alias('initial_data').join(to_update_df.alias('other_data'), F.col('row_index')==F.col('row_number'), how='left')
final_df = final_df.select('initial_data.row_number', 'other_data.L1', 'other_data.L2')
final_df.show()
# +----------+--------+--------+
# |row_number| L1| L2|
# +----------+--------+--------+
# | 0|row 1 L1|row 1 L2|
# | 1|row 2 L1|row 2 L2|
# +----------+--------+--------+
这在性能方面肯定会更好。Pypark确实支持lit,我想请不要使用Python 2.7。给定无法引用functions.py中的“lit”。您可以从pyspark.sql.functions import*执行此操作,而不是像pyspark_func一样尝试导入pyspark.sql.functions。它给出了未解析的引用“lit”,因为不允许在UDF中使用dataframe API函数。先把这个修好,我试试看。L1到L6是通过从SOAP API响应XML中提取标记来设置的变量。每一张唱片都会不断变化。这使得我的实现变得有点棘手和困难。哦,如果它们对每一条记录都不断变化,那么它就是一个列表,对吗?希望与您的数据帧大小相同?是的。我正在以列表的形式填充每个数据帧行的这些字段。我将尝试一下,并让您知道。Cheesdone在源API本身使用了一些更改。感谢您在命令提示下在pyspark终端上选择inputslit。但是pycharmCool上没有,所以这是一些JIRA门票中存在的问题,让我看看是否可以为您获取这些门票。只有几个链接似乎显示了类似的问题。是的,我至少修复了pycharm上的lit问题。但我用相应的问题替换列的主要问题仍然很大,只是为了弄清楚,您提到的使用lit now as lit的scala代码在Pyspark中可用并不能解决这个问题。您是否也在尝试将字符串变量“one”转换为int变量1,假设从第一行获取L1值。。。?