Python PySpark:一步计算平均值、标准偏差和平均值周围的值
我的原始数据是表格格式的。它包含来自不同变量的观察结果。每个观察都带有变量名、时间戳和当时的值 变量[字符串]、时间[日期时间]、值[浮点] 数据以拼花地板的形式存储在HDFS中,并加载到Spark数据帧(df)中。从那个数据帧 现在,我想计算每个变量的默认统计数据,如平均值、标准偏差和其他。之后,一旦检索到平均值,我想过滤/计算与平均值密切相关的变量值 基于对我的答案,我提出了以下代码:Python PySpark:一步计算平均值、标准偏差和平均值周围的值,python,python-2.7,apache-spark,pyspark,Python,Python 2.7,Apache Spark,Pyspark,我的原始数据是表格格式的。它包含来自不同变量的观察结果。每个观察都带有变量名、时间戳和当时的值 变量[字符串]、时间[日期时间]、值[浮点] 数据以拼花地板的形式存储在HDFS中,并加载到Spark数据帧(df)中。从那个数据帧 现在,我想计算每个变量的默认统计数据,如平均值、标准偏差和其他。之后,一旦检索到平均值,我想过滤/计算与平均值密切相关的变量值 基于对我的答案,我提出了以下代码: from pyspark.sql.window import Window from pyspark.sq
from pyspark.sql.window import Window
from pyspark.sql.functions import *
from pyspark.sql.types import *
w1 = Window().partitionBy("Variable")
w2 = Window.partitionBy("Variable").orderBy("Time")
def stddev_pop_w(col, w):
#Built-in stddev doesn't support windowing
return sqrt(avg(col * col).over(w) - pow(avg(col).over(w), 2))
def isInRange(value, mean, stddev, radius):
try:
if (abs(value - mean) < radius * stddev):
return 1
else:
return 0
except AttributeError:
return -1
delta = col("Time").cast("long") - lag("Time", 1).over(w2).cast("long")
#f = udf(lambda (value, mean, stddev, radius): abs(value - mean) < radius * stddev, IntegerType())
#f2 = udf(lambda value, mean, stddev: isInRange(value, mean, stddev, 2), IntegerType())
#f3 = udf(lambda value, mean, stddev: isInRange(value, mean, stddev, 3), IntegerType())
df_ = df_all \
.withColumn("mean", mean("Value").over(w1)) \
.withColumn("std_deviation", stddev_pop_w(col("Value"), w1)) \
.withColumn("delta", delta) \
# .withColumn("stddev_2", f2("Value", "mean", "std_deviation")) \
# .withColumn("stddev_3", f3("Value", "mean", "std_deviation")) \
#df2.show(5, False)
从pyspark.sql.window导入窗口
从pyspark.sql.functions导入*
从pyspark.sql.types导入*
w1=窗口().partitionBy(“变量”)
w2=窗口.partitionBy(“变量”).orderBy(“时间”)
def STDEV_pop_w(列,w):
#内置stddev不支持窗口设置
返回sqrt(平均(柱*柱)。超过(w)-功率(平均(柱)。超过(w),2))
def isInRange(值、平均值、标准差、半径):
尝试:
如果(abs(值-平均值)<半径*标准差):
返回1
其他:
返回0
除属性错误外:
返回-1
delta=col(“Time”).cast(“long”)-lag(“Time”,1)。over(w2)。cast(“long”)
#f=udf(λ(值、平均值、标准差、半径):abs(值-平均值)
问题:最后两行注释无效。它将给出AttributeError,因为stddev和mean的传入值为null。我猜这是因为我所指的列也是动态计算的,在那个时刻没有任何值但是有没有办法做到这一点呢?
目前,我正在进行第二次跑步,如下所示:
df = df_.select("*", \
abs(df_.Value - df_.mean).alias("max_deviation_mean"), \
when(abs(df_.Value - df_.mean) < 2 * df_.std_deviation, 1).otherwise(1).alias("std_dev_mean_2"), \
when(abs(df_.Value - df_.mean) < 3 * df_.std_deviation, 1).otherwise(1).alias("std_dev_mean_3"))
df=df\选择(“*”\
abs(偏差值-偏差平均值)。别名(“最大偏差平均值”)\
当(abs(df_u.值-df_u.平均值)<2*df_u.标准偏差,1)。否则(1)。别名(“标准偏差平均值2”)\
当(abs(df_u.值-df_u.平均值)<3*df_u.标准偏差,1)。否则(1)。别名(“标准偏差平均值3”))
这无法工作,因为当您执行
from pyspark.sql.functions import *
您可以使用pyspark.sql.functions.abs
对内置的abs
进行阴影处理,它需要一个列而不是本地Python值作为输入
另外,您创建的自定义项不处理NULL
条目
- 不要使用
,除非您知道导入的确切内容。取而代之的是别名import*
或导入模块from pyspark.sql.functions import abs as abs_
from pyspark.sql import functions as sqlf sqlf.col("x")
- 始终检查UDF内的输入,除非必要,否则最好避免使用UDF
from pyspark.statcounter import StatCounter
# value[0] is the timestamp and value[1] is the float-value
# we are using two instances of StatCounter to sum-up two different statistics
def mergeValues(s1, v1, s2, v2):
s1.merge(v1)
s2.merge(v2)
return
def combineStats(s1, s2):
s1[0].mergeStats(s2[0])
s1[1].mergeStats(s2[1])
return
(df.aggregateByKey((StatCounter(), StatCounter()),
(lambda s, values: mergeValues(s[0], values[0], s[1], values[1]),
(lambda s1, s2: combineStats(s1, s2))
.mapValues(lambda s: ( s[0].min(), s[0].max(), s[1].max(), s[1].min(), s[1].mean(), s[1].variance(), s[1].stddev,() s[1].count()))
.collect())
你是说当我更改导入时它会工作?我是说这和缺少NULL/None处理是明显的问题。可能还有其他问题。