我想在PySpark 2.0中执行一项操作,这种操作很容易作为df.rdd.map
执行,但由于出于性能原因我宁愿呆在Dataframe执行引擎内,我想找一个仅使用Dataframe操作执行此操作的方法。
RDD风格的操作是这样的:
def precision_formatter(row):
formatter = "%.{}f".format(row.precision)
return row + [formatter % row.amount_raw / 10 ** row.precision]
df = df.rdd.map(precision_formatter)
基本上,我有一个列告诉我,对于每一行,我的字符串格式化操作的精度应该是多少,并且我希望根据该精度选择性地将'amount_raw'列格式化为字符串。
答案 0 :(得分:0)
我不知道如何使用一列或多列的内容作为另一列操作的输入。我最接近的是建议使用Column.when
一组外部定义的布尔运算,这些运算对应于列或列中可能的布尔条件/个案集合。
在这种特定情况下,例如,如果您可以获得(或更好地,已经拥有)row.precision
的所有可能值,那么您可以迭代该集合并应用Column.when
操作集合中的每个值。我相信这个集合可以通过df.select('precision').distinct().collect()
获得。
由于pyspark.sql.functions.when
和Column.when
操作本身会返回Column
个对象,因此您可以迭代集合中的项目(但是已获取)并保持“追加”{{1以编程方式相互操作,直到你用尽了集合:
when
答案 1 :(得分:0)
您可以使用python UDF执行此操作。它们可以获取尽可能多的输入值(来自行的列的值)并吐出单个输出值。它看起来像这样:
from pyspark.sql import types as T, functions as F
from pyspark.sql.function import udf, col
# Create example data frame
schema = T.StructType([
T.StructField('precision', T.IntegerType(), False),
T.StructField('value', T.FloatType(), False)
])
data = [
(1, 0.123456),
(2, 0.123456),
(3, 0.123456)
]
rdd = sc.parallelize(data)
df = sqlContext.createDataFrame(rdd, schema)
# Define UDF and apply it
def format_func(precision, value):
format_str = "{:." + str(precision) + "f}"
return format_str.format(value)
format_udf = F.udf(format_func, T.StringType())
new_df = df.withColumn('formatted', format_udf('precision', 'value'))
new_df.show()
此外,如果您要使用全局值而不是列精度值,则可以在调用时使用lit(..)函数:
new_df = df.withColumn('formatted', format_udf(F.lit(2), 'value'))