python - পিএসপার্কে সর্বাধিক মান সহ গ্রুপবাইয়ের কলাম এবং ফিল্টার সারি




apache-spark pyspark (2)

আমি প্রায় নিশ্চিত যে এটি এর আগে জিজ্ঞাসা করা হয়েছিল, কিন্তু স্ট্যাকওভারফ্লো দিয়ে অনুসন্ধান করা আমার প্রশ্নের উত্তর দেয়নি। [2] সদৃশ নয় যেহেতু আমি সর্বাধিক ঘন আইটেমটি নয়, সর্বোচ্চ মান চাই। আমি পিএসপার্কে নতুন এবং সত্যিই সহজ কিছু করার চেষ্টা করছি: আমি "A" কলামটি গ্রুপপায়া করতে চাই এবং তারপরে কেবলমাত্র "বি" কলামে সর্বাধিক মান প্রাপ্ত প্রতিটি গ্রুপের সারিটি রাখি। এটার মত:

df_cleaned = df.groupBy("A").agg(F.max("B"))

দুর্ভাগ্যক্রমে, এটি অন্য সমস্ত কলামগুলি ছুঁড়ে ফেলেছে - df_cleaned এ কেবলমাত্র "A" কলাম এবং বি এর সর্বাধিক মান রয়েছে I আমি কীভাবে সারিগুলি রাখব? ("এ", "বি", "সি" ...)


আপনি Window ব্যবহার করে udf ছাড়াই এটি করতে পারেন।

নিম্নলিখিত উদাহরণ বিবেচনা করুন:

import pyspark.sql.functions as f
data = [
    ('a', 5),
    ('a', 8),
    ('a', 7),
    ('b', 1),
    ('b', 3)
]
df = sqlCtx.createDataFrame(data, ["A", "B"])
df.show()
#+---+---+
#|  A|  B|
#+---+---+
#|  a|  5|
#|  a|  8|
#|  a|  7|
#|  b|  1|
#|  b|  3|
#+---+---+

A কলাম দ্বারা বিভাজনে একটি Window তৈরি করুন এবং প্রতিটি গ্রুপের সর্বাধিক গণনা করতে এটি ব্যবহার করুন। তারপরে সারিগুলিকে ফিল্টার করুন যাতে কলাম B মানটি সর্বোচ্চের সমান।

from pyspark.sql import Window
w = Window.partitionBy('A')
df.withColumn('maxB', f.max('B').over(w))\
    .where(f.col('B') == f.col('maxB'))\
    .drop('maxB')\
    .show()
#+---+---+
#|  A|  B|
#+---+---+
#|  a|  8|
#|  b|  3|
#+---+---+

বা সমপর্যায়ের সাথে pyspark-sql ব্যবহার:

df.registerTempTable('table')
q = "SELECT A, B FROM (SELECT *, MAX(B) OVER (PARTITION BY A) AS maxB FROM table) M WHERE B = maxB"
sqlCtx.sql(q).show()
#+---+---+
#|  A|  B|
#+---+---+
#|  b|  3|
#|  a|  8|
#+---+---+

আর একটি সম্ভাব্য পন্থা হ'ল ডেটা ফ্রেমে যোগদানের জন্য "বামত্মী" উল্লেখ করে নিজের সাথে যুক্ত হওয়া। এই জাতীয় যোগদানের বাম পাশের ডেটাফ্রেমের সমস্ত কলাম এবং ডানদিকে কোনও কলাম নেই includes

উদাহরণ স্বরূপ:

import pyspark.sql.functions as f
data = [
    ('a', 5, 'c'),
    ('a', 8, 'd'),
    ('a', 7, 'e'),
    ('b', 1, 'f'),
    ('b', 3, 'g')
]
df = sqlContext.createDataFrame(data, ["A", "B", "C"])
df.show()
+---+---+---+
|  A|  B|  C|
+---+---+---+
|  a|  5|  c|
|  a|  8|  d|
|  a|  7|  e|
|  b|  1|  f|
|  b|  3|  g|
+---+---+---+

কলাম A দ্বারা কলাম B এর সর্বাধিক মান নির্বাচন করে নির্বাচন করা যেতে পারে:

df.groupBy('A').agg(f.max('B')
+---+---+
|  A|  B|
+---+---+
|  a|  8|
|  b|  3|
+---+---+

এই ভাবটি একটি বাম আধা যোগদানের ডান পাশ হিসাবে ব্যবহার করা, এবং প্রাপ্ত কলাম max(B) এর মূল নাম B নামকরণ করে, আমরা প্রয়োজনীয় ফলাফলটি পেতে পারি:

df.join(df.groupBy('A').agg(f.max('B').alias('B')),on='B',how='leftsemi').show()
+---+---+---+
|  B|  A|  C|
+---+---+---+
|  3|  b|  g|
|  8|  a|  d|
+---+---+---+

এই সমাধানের পিছনে শারীরিক পরিকল্পনা এবং গ্রহণযোগ্য উত্তর থেকে আলাদা এবং এটি এখনও বড় করে ডেটাফ্রেমে আরও ভাল কোনটি সম্পাদন করবে তা আমার কাছে পরিষ্কার নয়।

একই ফলাফলটি স্পার্ক এসকিউএল সিনট্যাক্স ব্যবহার করে পাওয়া যায়:

df.registerTempTable('table')
q = '''SELECT *
FROM table a LEFT SEMI
JOIN (
    SELECT 
        A,
        max(B) as max_B
    FROM table
    GROUP BY A
    ) t
ON a.A=t.A AND a.B=t.max_B
'''
sqlContext.sql(q).show()
+---+---+---+
|  A|  B|  C|
+---+---+---+
|  b|  3|  g|
|  a|  8|  d|
+---+---+---+




apache-spark-sql