如何在pyspark中找到变异系数(CV)?

如何在pyspark中找到变异系数(CV)?,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我有2个pyspark数据帧,我想找出这两个数据帧的变异系数 dataframe1: hours total 00 75969.0 01 75302.0 02 74636.0 03 73969.0 04 73302.0 05 72635.0 数据框架2:- hour

我有2个pyspark数据帧,我想找出这两个数据帧的变异系数

dataframe1:

          hours    total

           00     75969.0
           01     75302.0
           02     74636.0
           03     73969.0
           04     73302.0
           05     72635.0
数据框架2:-

            hours   total1

             00      71535
             01      71182
             02      77628
             03      75984
             04      75276
             05      67259
我希望输出如下:-

数据框架3:-

      hours       total        total1   CV
       00        75969.0        71535   3.006020
       01        75302.0        71182   2.812594
       02        74636.0        77628   1.965008
       03        73969.0        75984   1.343754
       04        73302.0        75276   1.328595
       05        72635.0        67259   3.842910
我已经通过将pyspark数据帧转换为pandas数据帧完成了这些工作,但我想计算CV而不去pandas。 我做过这样的事

     pd1=dataframe1.toPandas()
     pd2=dataframe2.toPandas()
     a4=[]
     list1=[]
     count=len(pd1)  
     print(count)
     import numpy as np
     for i in range(count):
         del a4[:]
         p9=(pd1.total[i])
         p10=(pd2.total1[i])
         a4.append(p10)
         a4.append(p9)
         standard_d1=np.std(a4,ddof=0)
         mean1=np.mean(a4)
         cv=(standard_d1/mean1)*100
         list1.append(cv)
     pd1['cv']=list1

因为这里只有两个元素,所以我们有一个属性
standard_dev=|total-total1 |/2
。由于
mean=(total+total1)/2
,我们有
CV=100*| total-total1/(total+total1)

因此:

from pyspark.sql import functions as F
df = dataframe1.join(dataframe2, 'hours', 'inner')
df_final = df.withColumn('CV', F.lit(100) * F.abs(df['total'] - df['total1']) / (df['total'] + df['total1']))

有几种方法可以解决此问题:

  • 使用
    窗口
  • 使用
    udf
  • 使用
    window
    +
    udf

    • 首先,让我们构建数据框架:
    • 仅使用
      udf
    • 使用
      窗口
    • 使用
      window
      +
      udf
    以上所有方法都会给出结果:

    +-----+---------+
    |hours|       CV|
    +-----+---------+
    |    0|  3.00602|
    |    1| 2.812594|
    |    2|1.9650081|
    |    3|1.3437544|
    |    4| 1.328595|
    |    5|3.8429096|
    +-----+---------+
    

    感谢您宝贵的时间,但计算时间更长。@niuer
    
    @pandas_udf(FloatType(), PandasUDFType.GROUPED_AGG)
    def _udf(v):
        return 100.0*np.std(v, ddof=0)/np.mean(v)
    
    df = df.groupBy('hours').agg(_udf(df['total']).alias('CV')).orderBy('hours')
    df.show()
    
    
    w = Window.partitionBy('hours')
    df = df.withColumn('std', F.stddev_pop('total').over(w))
    df = df.withColumn('mean', F.mean('total').over(w))
    df = df.withColumn('CV', 100.0*df['std']/df['mean']).dropDuplicates(['hours']).drop(*['total', 'std', 'mean']).orderBy('hours')
    df.show()
    
    w = Window.partitionBy('hours')
    df = df.withColumn('CV',_udf('total').over(w)).dropDuplicates(['hours']).orderBy('hours')
    df.show()
    
    +-----+---------+
    |hours|       CV|
    +-----+---------+
    |    0|  3.00602|
    |    1| 2.812594|
    |    2|1.9650081|
    |    3|1.3437544|
    |    4| 1.328595|
    |    5|3.8429096|
    +-----+---------+