数据框中列的几何平均值

时间:2017-02-23 15:32:39

标签: pyspark spark-dataframe pyspark-sql

我使用此代码计算数据框中所有行的几何平均值:

from pyspark.sql.functions import rand, randn, sqrt
df = sqlContext.range(0, 10)    
df = df.select(rand(seed=10).alias("c1"), randn(seed=27).alias("c2"))

df.show()

newdf = df.withColumn('total', sqrt(sum(df[col] for col in df.columns)))
newdf.show()

显示:

enter image description here

要计算列的几何平均值而不是行,我认为此代码应该足够了:

newdf = df.withColumn('total', sqrt(sum(df[row] for row in df.rows)))

但这引发了错误:NameError: global name 'row' is not defined

因此,访问列的api与访问行不同。

我应该格式化数据以将行转换为列然后重复使用工作算法:newdf = df.withColumn('total', sqrt(sum(df[col] for col in df.columns)))还是有解决方案按原样处理行和列?

1 个答案:

答案 0 :(得分:3)

我不确定你对几何平均数的定义是否正确。根据{{​​3}},几何平均值定义为n个数的乘积的第n个根。根据同一页面,几何平均值也可以表示为对数算术平均值的指数。我将使用它来计算每列的几何平均值。

您可以通过将c1c2的列数据合并到名为value的新列中来计算几何平均值,该列存储column中的源列名称。在重新格式化数据之后,通过按columnc1c2)分组并计算每组的对数值的算术平均值的指数来确定几何平均值。在此计算中,NaN值将被忽略。

from pyspark.sql import functions as F

df = sqlContext.range(0, 10)    
df = df.select(F.rand(seed=10).alias("c1"), F.randn(seed=27).alias("c2"))
df_id = df.withColumn("id", F.monotonically_increasing_id())

kvp = F.explode(F.array([F.struct(F.lit(c).alias("column"), F.col(c).alias("value")) for c in df.columns])).alias("kvp")
df_pivoted = df_id.select(['id'] + [kvp]).select(['id'] + ["kvp.column", "kvp.value"])
df_geometric_mean = df_pivoted.groupBy(['column']).agg(F.exp(F.avg(F.log(df_pivoted.value))))
df_geometric_mean.withColumnRenamed("EXP(avg(LOG(value)))", "geometric_mean").show()

返回:

+------+-------------------+
|column|     geometric_mean|
+------+-------------------+
|    c1|0.25618961513533134|
|    c2|  0.415119290980354|
+------+-------------------+

除了精度之外,这些几何意味着与scipy匹配的几何平均回报也会被忽略。

from scipy.stats.mstats import gmean
c1=[x['c1'] for x in df.collect() if x['c1']>0]
c2=[x['c2'] for x in df.collect() if x['c2']>0]
print 'c1 : {0}\r\nc2 : {1}'.format(gmean(c1),gmean(c2))

此代码段返回:

|    c1|0.256189615135|
|    c2|0.41511929098|