web-dev-qa-db-ja.com

pyspark近似量子関数

これらの列idpricetimestampを含むデータフレームがあります。

idでグループ化された中央値を見つけたいです。

このコードを使用して見つけていますが、このエラーが発生しています。

from pyspark.sql import DataFrameStatFunctions as statFunc
windowSpec = Window.partitionBy("id")
median = statFunc.approxQuantile("price",
                                 [0.5],
                                 0) \
                 .over(windowSpec)

return df.withColumn("Median", median)

DataFrameStatFunctionsを使用して新しい列に値を入力することはできませんか?

TypeError: unbound method approxQuantile() must be called with DataFrameStatFunctions instance as first argument (got str instance instead)
8
BK C.

確かに、新しいデータフレーム列に値を入力するためにapproxQuantileを使用することはnot可能ですが、これが理由ですこのエラー。残念ながら、 私は多くのSpark(特にPySpark)機能とそれらの欠如の場合にそうであるように 適切な文書の。

まず、1つではなく、twoapproxQuantileメソッド; first one は標準のDataFrameクラスの一部です。つまり、DataFrameStatFunctionsをインポートする必要はありません。

spark.version
# u'2.1.1'

sampleData = [("bob","Developer",125000),("mark","Developer",108000),("carl","Tester",70000),("peter","Developer",185000),("jon","Tester",65000),("roman","Tester",82000),("simon","Developer",98000),("eric","Developer",144000),("carlos","Tester",75000),("henry","Developer",110000)]

df = spark.createDataFrame(sampleData, schema=["Name","Role","Salary"])
df.show()
# +------+---------+------+ 
# |  Name|     Role|Salary|
# +------+---------+------+
# |   bob|Developer|125000| 
# |  mark|Developer|108000|
# |  carl|   Tester| 70000|
# | peter|Developer|185000|
# |   jon|   Tester| 65000|
# | roman|   Tester| 82000|
# | simon|Developer| 98000|
# |  eric|Developer|144000|
# |carlos|   Tester| 75000|
# | henry|Developer|110000|
# +------+---------+------+

med = df.approxQuantile("Salary", [0.5], 0.25) # no need to import DataFrameStatFunctions
med
# [98000.0]

2番目のDataFrameStatFunctionsの一部ですが、そのまま使用すると、エラーが報告されます:

from pyspark.sql import DataFrameStatFunctions as statFunc
med2 = statFunc.approxQuantile( "Salary", [0.5], 0.25)
# TypeError: unbound method approxQuantile() must be called with DataFrameStatFunctions instance as first argument (got str instance instead)

正しい使い方は

med2 = statFunc(df).approxQuantile( "Salary", [0.5], 0.25)
med2
# [82000.0]

これについては、PySparkのドキュメントで簡単な例を見つけることはできませんが(自分で理解するのに少し時間がかかりました)...最良の部分は? 2つの値はnot equalです。

med == med2
# False

これは、使用されている非決定論的なアルゴリズムによるものと思われます(結局、approximate medianであると想定されています)。異なる値(およびここで報告する値とは異なる)-少しでも実験して感覚をつかむことをお勧めします...

しかし、すでに述べたように、これはapproxQuantileを使用して新しいデータフレーム列に値を入力できない理由ではありません。正しい構文を使用しても、別のエラーが発生します。

df2 = df.withColumn('median_salary', statFunc(df).approxQuantile( "Salary", [0.5], 0.25))
# AssertionError: col should be Column

ここで、colwithColumn操作の2番目の引数、つまりapproxQuantileを指し、エラーメッセージはColumn型ではないことを示しています-実際、それはリストです:

type(statFunc(df).approxQuantile( "Salary", [0.5], 0.25))
# list

そのため、列の値を入力するとき、SparkはColumn型の引数を必要とし、リストを使用できません。ここでは、ロールごとの平均値を持つ新しい列を作成する例を示します。中央値:

import pyspark.sql.functions as func
from pyspark.sql import Window

windowSpec = Window.partitionBy(df['Role'])
df2 = df.withColumn('mean_salary', func.mean(df['Salary']).over(windowSpec))
df2.show()
# +------+---------+------+------------------+
# |  Name|     Role|Salary|       mean_salary| 
# +------+---------+------+------------------+
# |  carl|   Tester| 70000|           73000.0| 
# |   jon|   Tester| 65000|           73000.0|
# | roman|   Tester| 82000|           73000.0|
# |carlos|   Tester| 75000|           73000.0|
# |   bob|Developer|125000|128333.33333333333|
# |  mark|Developer|108000|128333.33333333333| 
# | peter|Developer|185000|128333.33333333333| 
# | simon|Developer| 98000|128333.33333333333| 
# |  eric|Developer|144000|128333.33333333333|
# | henry|Developer|110000|128333.33333333333| 
# +------+---------+------+------------------+

これは、approxQuantileとは異なり、meanColumnを返すためです。

type(func.mean(df['Salary']).over(windowSpec))
# pyspark.sql.column.Column
37
desertnaut

グループ内の変位値の計算(集計)の例

グループの集約関数が欠落しているため、名前(percentile_approxこの場合):

from pyspark.sql.column import Column, _to_Java_column, _to_seq

def from_name(sc, func_name, *params):
    """
       create call by function name 
    """
    callUDF = sc._jvm.org.Apache.spark.sql.functions.callUDF
    func = callUDF(func_name, _to_seq(sc, *params, _to_Java_column))
    return Column(func)

適用percentile_approx groupByの関数:

from pyspark.sql import SparkSession
from pyspark.sql import functions as f

spark = SparkSession.builder.getOrCreate()
sc = spark.sparkContext

# build percentile_approx function call by name: 
target = from_name(sc, "percentile_approx", [f.col("salary"), f.lit(0.95)])


# load dataframe for persons data 
# with columns "person_id", "group_id" and "salary"
persons = spark.read.parquet( ... )

# apply function for each group
persons.groupBy("group_id").agg(
    target.alias("target")).show()
1
volhv