如何在pyspark中找到变异系数(CV)?
我有2个pyspark数据帧,我想找出这两个数据帧的变异系数 dataframe1:如何在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
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|
+-----+---------+