项目场景:
在做特征分桶之前的时候,先想对df的一列取log。
问题描述:
网上搜了好久的方法,都没有说怎么解决,大概搜到了2种相近的解决方法,都不尽人意。
第一个是用math.log(),第二个使用np.log()。可以看出如下都会报错,math只能处理real number,不能处理column。np的话会把表头带进去导致无法计算。
df = df.withColumn('mgame_online_90_xxxc',math.log(df.mgame_online_90_rpg+1)+1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-16-5a6abbda081b> in <module>
1 # import numpy as np
----> 2 df = df.withColumn('mgame_online_90_xxxc',math.log(df.mgame_online_90_rpg+1)+1)
TypeError: must be real number, not Column
import numpy as np
df = df.withColumn('mgame_online_90_xxxc',np.log(df.mgame_online_90_rpg+1)+1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-15-f6debe1c3dd1> in <module>
1 import numpy as np
----> 2 df = df.withColumn('mgame_online_90_xxxc',np.log(df.mgame_online_90_rpg+1)+1)
TypeError: loop of ufunc does not support argument 0 of type Column which has no callable log method
原因分析:
想了一下午觉得np可能会有突破方式,比如把表头去掉,然后最后再加上之类的操作。但是感觉异常复杂,stack overflow也没找到相关的解决方法。
第二天来想,能不能用lambda表达式+map之类的处理方式。找了半天还是没有,最后突发奇想去官方文档里面搜“log”关键字,说不定有呢?
解决方案:
果然在里面发现了pyspark.sql.functions.log方法。http://spark.apache.org/docs/1.6.2/api/python/pyspark.sql.html#pyspark.sql.functions.log
最后还是应该去看官方文档,应该早点去看的啊。。。
pyspark.sql.functions.log(arg1, arg2=None)
Returns the first argument-based logarithm of the second argument.
If there is only one argument, then this takes the natural logarithm of the argument.
>>> df.select(log(10.0, df.age).alias('ten')).map(lambda l: str(l.ten)[:7]).collect() ['0.30102', '0.69897']
>>> df.select(log(df.age).alias('e')).map(lambda l: str(l.e)[:7]).collect() ['0.69314', '1.60943']
New in version 1.5.
所以直接import,然后用就行了。
from pyspark.sql.functions import col, log
df = df.withColumn('mgame_online_90_xxxc',log(col("mgame_online_90_xxxc")+1)+1)