统计列并行计算

时间:2018-09-12 04:16:54

标签: hive pyspark statistics

Best way to get the max value in a Spark dataframe column

这篇文章显示了如何在类似表的表上运行聚合(不同,最小,最大):

for colName in df.columns:
    dt = cd[[colName]].distinct().count()
    mx = cd.agg({colName: "max"}).collect()[0][0]
    mn = cd.agg({colName: "min"}).collect()[0][0]
    print(colName, dt, mx, mn)

这可以通过计算统计信息轻松完成。 Hive和spark的统计信息不同:

  • 配置单元提供-不同,最大,最小,空值,长度,版本
  • Spark Gives-计数,平均值,stddev,最小值,最大值

看起来有很多统计数据被计算出来。如何使用一个命令获取所有列的所有列?

但是,我有1000列,并且连续执行此操作非常慢。假设我想在每列上计算其他函数,例如“标准偏差”,该如何并行完成?

2 个答案:

答案 0 :(得分:1)

您可以根据需要在agg中放入任意多个表达式,当它们被收集时,它们都将立即被计算。结果是包含所有值的一行。这是一个示例:

from pyspark.sql.functions import min, max, countDistinct

r = df.agg(
  min(df.col1).alias("minCol1"),
  max(df.col1).alias("maxCol1"),
  (max(df.col1) - min(df.col1)).alias("diffMinMax"),
  countDistinct(df.col2).alias("distinctItemsInCol2"))
r.printSchema()
# root
#  |-- minCol1: long (nullable = true)
#  |-- maxCol1: long (nullable = true)
#  |-- diffMinMax: long (nullable = true)
#  |-- distinctItemsInCol2: long (nullable = false)

row = r.collect()[0]
print(row.distinctItemsInCol2, row.diffMinMax)
# (10, 9)

您还可以在此处使用字典语法,但是更复杂的事情很难管理。

答案 1 :(得分:1)

您可以使用pyspark.sql.DataFrame.describe()来获取适用于所有统计信息的总计统计信息,例如计数,均值,最小值,最大值和标准偏差。 (如果您不传递任何参数,则默认情况下将返回所有列的统计信息)

df = spark.createDataFrame(
    [(1, "a"),(2, "b"), (3, "a"), (4, None), (None, "c")],["id", "name"]
)
df.describe().show()
#+-------+------------------+----+
#|summary|                id|name|
#+-------+------------------+----+
#|  count|                 4|   4|
#|   mean|               2.5|null|
#| stddev|1.2909944487358056|null|
#|    min|                 1|   a|
#|    max|                 4|   c|
#+-------+------------------+----+

如您所见,这些统计信息将忽略任何null值。

如果您使用的是Spark 2.3版,则还有pyspark.sql.DataFrame.summary()支持以下聚合:

  

计数-平均值-标准差-最小值-最大值-指定为百分比的任意近似百分位数(例如75%)

df.summary("count", "min", "max").show()
#+-------+------------------+----+
#|summary|                id|name|
#+-------+------------------+----+
#|  count|                 4|   4|
#|    min|                 1|   a|
#|    max|                 4|   c|
#+-------+------------------+----+

如果您想要所有列的其他汇总统计信息,则还可以对pyspark.sql.DataFrame.agg()使用列表推导。例如,如果您想复制Hive给出的内容(不同,最大,最小和空值-我不确定长度和版本是什么意思):

import pyspark.sql.functions as f
from itertools import chain

agg_distinct = [f.countDistinct(c).alias("distinct_"+c) for c in df.columns]
agg_max = [f.max(c).alias("max_"+c) for c in df.columns]
agg_min = [f.min(c).alias("min_"+c) for c in df.columns]
agg_nulls = [f.count(f.when(f.isnull(c), c)).alias("nulls_"+c) for c in df.columns]

df.agg(
    *(chain.from_iterable([agg_distinct, agg_max, agg_min, agg_nulls]))
).show()
#+-----------+-------------+------+--------+------+--------+--------+----------+
#|distinct_id|distinct_name|max_id|max_name|min_id|min_name|nulls_id|nulls_name|
#+-----------+-------------+------+--------+------+--------+--------+----------+
#|          4|            3|     4|       c|     1|       a|       1|         1|
#+-----------+-------------+------+--------+------+--------+--------+----------+

尽管此方法将返回一行,而不是像describe()summary()那样为每个统计信息返回一行。