MaxU 的回答既好又高效。这篇文章概述了另一种有效的方法,有助于保持代码库的整洁(使用 quinn 库)。
假设你有以下DataFrame:
+---+-----+--------+-------+
| id| name|emp.city|emp.sal|
+---+-----+--------+-------+
| 12| bob|New York| 80|
| 99|alice| Atlanta| 90|
+---+-----+--------+-------+
以下是如何将所有列中的点替换为下划线。
import quinn
def dots_to_underscores(s):
return s.replace('.', '_')
actual_df = df.transform(quinn.with_columns_renamed(dots_to_underscores))
actual_df.show()
这是结果actual_df:
+---+-----+--------+-------+
| id| name|emp_city|emp_sal|
+---+-----+--------+-------+
| 12| bob|New York| 80|
| 99|alice| Atlanta| 90|
+---+-----+--------+-------+
让我们使用explain() 来验证这个函数是否有效地执行:
actual_df.explain(True)
这是输出的逻辑计划:
== Parsed Logical Plan ==
'Project ['id AS id#50, 'name AS name#51, '`emp.city` AS emp_city#52, '`emp.sal` AS emp_sal#53]
+- LogicalRDD [id#29, name#30, emp.city#31, emp.sal#32], false
== Analyzed Logical Plan ==
id: string, name: string, emp_city: string, emp_sal: string
Project [id#29 AS id#50, name#30 AS name#51, emp.city#31 AS emp_city#52, emp.sal#32 AS emp_sal#53]
+- LogicalRDD [id#29, name#30, emp.city#31, emp.sal#32], false
== Optimized Logical Plan ==
Project [id#29, name#30, emp.city#31 AS emp_city#52, emp.sal#32 AS emp_sal#53]
+- LogicalRDD [id#29, name#30, emp.city#31, emp.sal#32], false
== Physical Plan ==
*(1) Project [id#29, name#30, emp.city#31 AS emp_city#52, emp.sal#32 AS emp_sal#53]
可以看到解析出来的逻辑计划和物理计划几乎是一样的,所以Catalyst优化器不需要做太多的优化工作。它将id AS id#50 转换为id#29,但这并没有太多的工作。
with_some_columns_renamed 方法生成更高效的解析计划。
def dots_to_underscores(s):
return s.replace('.', '_')
def change_col_name(s):
return '.' in s
actual_df = df.transform(quinn.with_some_columns_renamed(dots_to_underscores, change_col_name))
actual_df.explain(True)
这个解析后的计划只用点来别名列。
== Parsed Logical Plan ==
'Project [unresolvedalias('id, None), unresolvedalias('name, None), '`emp.city` AS emp_city#42, '`emp.sal` AS emp_sal#43]
+- LogicalRDD [id#34, name#35, emp.city#36, emp.sal#37], false
== Analyzed Logical Plan ==
id: string, name: string, emp_city: string, emp_sal: string
Project [id#34, name#35, emp.city#36 AS emp_city#42, emp.sal#37 AS emp_sal#43]
+- LogicalRDD [id#34, name#35, emp.city#36, emp.sal#37], false
== Optimized Logical Plan ==
Project [id#34, name#35, emp.city#36 AS emp_city#42, emp.sal#37 AS emp_sal#43]
+- LogicalRDD [id#34, name#35, emp.city#36, emp.sal#37], false
== Physical Plan ==
*(1) Project [id#34, name#35, emp.city#36 AS emp_city#42, emp.sal#37 AS emp_sal#43]
更多信息为什么循环遍历 DataFrame 并多次调用 withColumnRenamed 会创建过于复杂的解析计划,应该避免。