Spark Lambda函数报NameError:如何计算私立学校录取率?
解决PySpark中Lambda函数的NameError问题
你的问题根源出在map操作的lambda写法上——你错误地把要返回的两个值拆成了map方法的两个参数,导致第二个参数里的x找不到定义。具体来说:
你写的private.map(lambda x: x[0], (x[3]/x[2]))会被Python解析为:第一个参数是lambda x: x[0],第二个参数是(x[3]/x[2])。这时候第二个参数里的x不在当前作用域内,自然触发NameError。
修复后的完整代码
你需要把学校名称和录取率包装成一个元组,作为lambda函数的整体返回值,这样整个lambda是一个合法的函数表达式:
from pyspark import SparkConf, SparkContext conf = SparkConf().setMaster("local").setAppName("accptRates") sc = SparkContext(conf = conf) lines = sc.textFile("file:/schoolData.csv") def parseLine(line): fields = line.split(",") name = fields[0] private = fields[1] apps = int(fields[2]) accept = int(fields[3]) return (name, private, apps, accept) extheader = lines.first() # 提取表头 header=sc.parallelize([extheader]) schools = lines.subtract(header) # 过滤掉表头 rdd = schools.map(parseLine) private = rdd.filter(lambda x: "Yes" in x[1]) # 修复lambda:将返回值包装成元组 rates = private.map(lambda x: (x[0], x[3]/x[2])).take(10) print(rates) sc.stop()
额外实用建议
- 处理除零异常:如果存在申请数为0的学校,直接计算除法会触发
ZeroDivisionError,可以在lambda里增加判断逻辑:
rates = private.map(lambda x: (x[0], x[3]/x[2] if x[2] != 0 else 0.0)).take(10)
- 改用SparkSession(推荐):Spark 2.0+更推荐使用DataFrame API,写法更简洁且自动处理表头,无需手动过滤:
from pyspark.sql import SparkSession spark = SparkSession.builder.master("local").appName("accptRates").getOrCreate() # 直接读取CSV并识别表头和数据类型 df = spark.read.csv("file:/schoolData.csv", header=True, inferSchema=True) private_df = df.filter(df.private == "Yes") # 计算录取率并命名列 rates_df = private_df.select("name", (private_df.accept / private_df.apps).alias("acceptance_rate")) rates = rates_df.limit(10).collect() print(rates) spark.stop()
内容的提问来源于stack exchange,提问作者Jacob Myer
相关产品推荐
相关产品推荐

