我使用此代码计算数据框中所有行的几何平均值:
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()
显示:
要计算列的几何平均值而不是行,我认为此代码应该足够了:
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)))
还是有解决方案按原样处理行和列?
答案 0 :(得分:3)
我不确定你对几何平均数的定义是否正确。根据{{3}},几何平均值定义为n个数的乘积的第n个根。根据同一页面,几何平均值也可以表示为对数算术平均值的指数。我将使用它来计算每列的几何平均值。
您可以通过将c1
和c2
的列数据合并到名为value
的新列中来计算几何平均值,该列存储column
中的源列名称。在重新格式化数据之后,通过按column
(c1
或c2
)分组并计算每组的对数值的算术平均值的指数来确定几何平均值。在此计算中,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|