当前位置: 首页 > 科技观察

学这门语言两个月了,还卡在加减乘除...

时间:2023-03-18 00:41:40 科技观察

因为业务需要(项目技术栈是spark2+),兴冲冲的去借书7、8月份学校图书馆,学习了scala+spark之后,也写了很多博文,其中有一些用来推送:Scala,一门“特立独行”的语言!,[疑惑]如何提取特定行来自Spark的DataFrame?...但是在实际操作中,还是存在很多问题。有两个体会:看书(尤其是国内的教材)理解概念还可以,但对实际操作用处不大。当你接触一门新的编程语言时,首先应该阅读大量优秀的案例代码,了解数据类型。比如昨天早上纠结这个:请给spark中dataframe某列的编号。按理说不难。如果直接使用python的pandas:#pandasdf['sig_x']=df['x'].apply(lambdax:1/(1-np.exp(-x)))但spark不起作用。在spark中,用来创建新列的函数是withColumn,先传入函数名,再传入一个col对象。这个col对象有讲究。虽然今天觉得比较直观,容易理解,但是昨天处理了半天。首先,如果我想使用列x,我不能只是"x"因为它是一个字符串,我需要调用隐式转换函数$,而这个$实际上在spark.implicits._中。值得注意的是,spark是您的SparkSession实例。上面的内容如果不清楚,找资料会费点功夫。importspark.implicits._valdf_new=df.withColumn("x_new",$"x")上面的代码构造了一个新的df_new对象,它有列x_new和列x,两列的值完全一样。其次,在哪里可以找到我的操作功能?答案是org.apache.spark.sql.functions,因为它是一个col对象,可能没有重载数据类型常量的+-*/运算符,所以如果我们1-$"x"可能会报错:因为#"x"是一个col而1只是一个Int。我们所要做的就是将1变成一个col:在仔细研究之后,我发现了lit方法,也在org.apache.spark.sql.functions中。最终的解决方案如下。importspark.implicits._importorg.apache.spark.sql.functions.{fit,exp,negate}valdf_result=df_raw_result.withColumn("x_sig",lit(1.0)/(lit(1.0)+exp(negate($"x"))))其实实际代码比上面更复杂,因为"x"列实际上是一个vector对象,我不能直接用$"x"得到$"x"列的第一个vector(0)个元素,最后发现使用udf可以实现列的功能。importspark.implicits._importorg.apache.spark.sql.functions.{fit,exp,negate,udf}//获取向量中第一个元素valgetItem=udf((v:org.apache.spark.ml.linalg.DenseVector,i:Int)=>v(i))valdf_result=df_raw_result.withColumn("x_sig",lit(1.0)/(lit(1.0)+exp(negate(getItem($"x",lit(0))))))蟒蛇和斯卡拉?貌似python下的操作更简洁优雅,但我更喜欢用scala来写这个级别的项目。原因很简单。Scala对类型的严格要求,以及借鉴函数式编程的思想,让写代码变得如此酷。大部分问题都可以在编译的时候发现,配合IDEA的自动补全真的很舒服。到现在还没搞明白udf代表的是什么,基本的语法和框架思想还是要查和补的。