it-swarm.com.ru

Лучший способ получить максимальное значение в столбце данных Spark

Я пытаюсь найти лучший способ получить наибольшее значение в столбце данных Spark.

Рассмотрим следующий пример:

df = spark.createDataFrame([(1., 4.), (2., 5.), (3., 6.)], ["A", "B"])
df.show()

Который создает:

+---+---+
|  A|  B|
+---+---+
|1.0|4.0|
|2.0|5.0|
|3.0|6.0|
+---+---+

Моя цель состоит в том, чтобы найти наибольшее значение в столбце A (при проверке это 3,0). Используя PySpark, я могу придумать четыре подхода:

# Method 1: Use describe()
float(df.describe("A").filter("summary = 'max'").select("A").collect()[0].asDict()['A'])

# Method 2: Use SQL
df.registerTempTable("df_table")
spark.sql("SELECT MAX(A) as maxval FROM df_table").collect()[0].asDict()['maxval']

# Method 3: Use groupby()
df.groupby().max('A').collect()[0].asDict()['max(A)']

# Method 4: Convert to RDD
df.select("A").rdd.max()[0]

Каждый из вышеперечисленных дает правильный ответ, но в отсутствие инструмента профилирования Spark я не могу сказать, какой из них лучше. 

Какие-либо идеи из интуиции или эмпиризма о том, какой из перечисленных методов наиболее эффективен с точки зрения времени выполнения Spark или использования ресурсов, или есть ли более прямой метод, чем описанные выше?

36
xenocyon
>df1.show()
+-----+--------------------+--------+----------+-----------+
|floor|           timestamp|     uid|         x|          y|
+-----+--------------------+--------+----------+-----------+
|    1|2014-07-19T16:00:...|600dfbe2| 103.79211|71.50419418|
|    1|2014-07-19T16:00:...|5e7b40e1| 110.33613|100.6828393|
|    1|2014-07-19T16:00:...|285d22e4|110.066315|86.48873585|
|    1|2014-07-19T16:00:...|74d917a1| 103.78499|71.45633073|

>row1 = df1.agg({"x": "max"}).collect()[0]
>print row1
Row(max(x)=110.33613)
>print row1["max(x)"]
110.33613

Ответ почти такой же, как method3. но кажется "asDict ()" в method3 можно удалить

28
Burt

Максимальное значение для определенного столбца данных может быть достигнуто с помощью -

your_max_value = df.agg({"your-column": "max"}).collect()[0][0]

11
Rudra Prasad Samal

Примечание: Spark предназначен для работы с большими данными - распределенными вычислениями. Размер примера DataFrame очень мал, поэтому порядок реальных примеров можно изменить относительно маленького примера.

Самый медленный: Method_1, потому что .describe ("A") вычисляет min, max, mean, stddev и count (5 вычислений по всему столбцу) 

Средний: Method_4, потому что .rdd (преобразование DF в RDD) замедляет процесс.

Быстрее: Method_3 ~ Method_2 ~ method_5, потому что логика очень похожа, поэтому оптимизатор катализатора Spark следует очень похожей логике с минимальным количеством операций (получить максимум определенного столбца, собрать кадр данных с одним значением); (.asDict () добавляет немного дополнительного времени по сравнению с 3,2 до 5) 

import pandas as pd
import time

time_dict = {}

dfff = self.spark.createDataFrame([(1., 4.), (2., 5.), (3., 6.)], ["A", "B"])
#--  For bigger/realistic dataframe just uncomment the following 3 lines
#lst = list(np.random.normal(0.0, 100.0, 100000))
#pdf = pd.DataFrame({'A': lst, 'B': lst, 'C': lst, 'D': lst})
#dfff = self.sqlContext.createDataFrame(pdf)

tic1 = int(round(time.time() * 1000))
# Method 1: Use describe()
max_val = float(dfff.describe("A").filter("summary = 'max'").select("A").collect()[0].asDict()['A'])
tac1 = int(round(time.time() * 1000))
time_dict['m1']= tac1 - tic1
print (max_val)

tic2 = int(round(time.time() * 1000))
# Method 2: Use SQL
dfff.registerTempTable("df_table")
max_val = self.sqlContext.sql("SELECT MAX(A) as maxval FROM df_table").collect()[0].asDict()['maxval']
tac2 = int(round(time.time() * 1000))
time_dict['m2']= tac2 - tic2
print (max_val)

tic3 = int(round(time.time() * 1000))
# Method 3: Use groupby()
max_val = dfff.groupby().max('A').collect()[0].asDict()['max(A)']
tac3 = int(round(time.time() * 1000))
time_dict['m3']= tac3 - tic3
print (max_val)

tic4 = int(round(time.time() * 1000))
# Method 4: Convert to RDD
max_val = dfff.select("A").rdd.max()[0]
tac4 = int(round(time.time() * 1000))
time_dict['m4']= tac4 - tic4
print (max_val)

tic5 = int(round(time.time() * 1000))
# Method 4: Convert to RDD
max_val = dfff.agg({"A": "max"}).collect()[0][0]
tac5 = int(round(time.time() * 1000))
time_dict['m5']= tac5 - tic5
print (max_val)

print time_dict

Результат на Edge-узле кластера в миллисекундах (мс): 

small DF (мс): {'m1': 7096, 'm2': 205, 'm3': 165, 'm4': 211, 'm5': 180}

больше DF (мс): {'m1': 10260, 'm2': 452, 'm3': 465, 'm4': 916, 'm5': 373}

9
Danylo Zherebetskyy

Еще один способ сделать это:

df.select(f.max(f.col("A")).alias("MAX")).limit(1).collect()[0].MAX

По моим данным, я получил следующие отметки:

df.select(f.max(f.col("A")).alias("MAX")).limit(1).collect()[0].MAX
CPU times: user 2.31 ms, sys: 3.31 ms, total: 5.62 ms
Wall time: 3.7 s

df.select("A").rdd.max()[0]
CPU times: user 23.2 ms, sys: 13.9 ms, total: 37.1 ms
Wall time: 10.3 s

df.agg({"A": "max"}).collect()[0][0]
CPU times: user 0 ns, sys: 4.77 ms, total: 4.77 ms
Wall time: 3.75 s

Все они дают одинаковый ответ

7
luminousmen

В случае, если некоторые задаются вопросом, как это сделать с помощью Scala (используя Spark 2.0. +), Здесь вы идете:

scala> df.createOrReplaceTempView("TEMP_DF")
scala> val myMax = spark.sql("SELECT MAX(x) as maxval FROM TEMP_DF").
    collect()(0).getInt(0)
scala> print(myMax)
117
3
Boern

Я считаю, что лучшим решением будет использование head()

Учитывая ваш пример:

+---+---+
|  A|  B|
+---+---+
|1.0|4.0|
|2.0|5.0|
|3.0|6.0|
+---+---+

Используя метод python agg и max, мы можем получить значение следующим образом:

from pyspark.sql.functions import max df.agg(max(df.A)).head()[0]

Это вернет: 3.0

Убедитесь, что у вас есть правильный импорт:
from pyspark.sql.functions import max Функция max, которую мы здесь используем, является библиотечной функцией pySPark sql, а не функцией max по умолчанию для python.

1
Vyom Shrivastava

в pyspark вы можете сделать это:

max(df.select('ColumnName').rdd.flatMap(lambda x: x).collect())
0
Grant Shannon

Вот ленивый способ сделать это, просто выполнив вычисления статистики:

df.write.mode("overwrite").saveAsTable("sampleStats")
Query = "ANALYZE TABLE sampleStats COMPUTE STATISTICS FOR COLUMNS " + ','.join(df.columns)
spark.sql(Query)

df.describe('ColName')

или же

spark.sql("Select * from sampleStats").describe('ColName')

или вы можете открыть Hive Shell и 

describe formatted table sampleStats;

Вы увидите статистику в свойствах - минимальная, максимальная, отличная, ноль и т.д.

0
user 923227
import org.Apache.spark.sql.SparkSession
import org.Apache.spark.sql.functions._

val testDataFrame = Seq(
  (1.0, 4.0), (2.0, 5.0), (3.0, 6.0)
).toDF("A", "B")

val (maxA, maxB) = testDataFrame.select(max("A"), max("B"))
  .as[(Double, Double)]
  .first()
println(maxA, maxB)

И результат (3.0,6.0), который совпадает с testDataFrame.agg(max($"A"), max($"B")).collect()(0). Однако testDataFrame.agg(max($"A"), max($"B")).collect()(0) возвращает List, [3.0,6.0]

0
hello-world