[英]pyspark: count number of occurrences of distinct elements in lists
我必須關注數據:
data = {'date': ['2014-01-01', '2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06'],
'flat': ['A;A;B', 'D;P;E;P;P', 'H;X', 'P;Q;G', 'S;T;U', 'G;C;G']}
data['date'] = pd.to_datetime(data['date'])
data = pd.DataFrame(data)
data['date'] = pd.to_datetime(data['date'])
spark = SparkSession.builder \
.master('local[*]') \
.config("spark.driver.memory", "500g") \
.appName('my-pandasToSparkDF-app') \
.getOrCreate()
spark.conf.set("spark.sql.execution.arrow.enabled", "true")
spark.sparkContext.setLogLevel("OFF")
df=spark.createDataFrame(data)
new_frame = df.withColumn("list", F.split("flat", "\;"))
我想添加一個新列,其中包含每個不同元素的出現次數(按升序排序)和另一個包含最大值的列:
+-------------------+-----------+---------------------+-----------+----+
| date| flat | list |occurrences|max |
+-------------------+-----------+---------------------+-----------+----+
|2014-01-01 00:00:00|A;A;B |['A','A','B'] |[1,2] |2 |
|2014-01-02 00:00:00|D;P;E;P;P |['D','P','E','P','P']|[1,1,3] |3 |
|2014-01-03 00:00:00|H;X |['H','X'] |[1,1] |1 |
|2014-01-04 00:00:00|P;Q;G |['P','Q','G'] |[1,1,1] |1 |
|2014-01-05 00:00:00|S;T;U |['S','T','U'] |[1,1,1] |1 |
|2014-01-06 00:00:00|G;C;G |['G','C','G'] |[1,2] |2 |
+-------------------+-----------+---------------------+-----------+----+
非常感謝!
對於Spark2.4+
,這可以在沒有多個 groupBys 和聚合的情況下實現(因為它們在大數據中是昂貴的 shuffle 操作)。 您可以使用高階函數transform
和aggregate
的one expression
來做到這一點。 這應該是 spark2.4 的規范解決方案。
from pyspark.sql import functions as F
df=spark.createDataFrame(data)
df.withColumn("list", F.split("flat","\;"))\
.withColumn("occurances", F.expr("""array_sort(transform(array_distinct(list), x-> aggregate(list, 0,(acc,t)->acc+IF(t=x,1,0))))"""))\
.withColumn("max", F.array_max("occurances"))\
.show()
+-------------------+---------+---------------+----------+---+
| date| flat| list|occurances|max|
+-------------------+---------+---------------+----------+---+
|2014-01-01 00:00:00| A;A;B| [A, A, B]| [1, 2]| 2|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| [1, 1, 3]| 3|
|2014-01-03 00:00:00| H;X| [H, X]| [1, 1]| 1|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| [1, 1, 1]| 1|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| [1, 1, 1]| 1|
|2014-01-06 00:00:00| G;C;G| [G, C, G]| [1, 2]| 2|
+-------------------+---------+---------------+----------+---+
您可以通過幾個 groupBy 語句來做到這一點,
首先你有一個像這樣的 dataframe,
+-------------------+---------+---------------+
| date| flat| list|
+-------------------+---------+---------------+
|2014-01-01 00:00:00| A;A;B| [A, A, B]|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]|
|2014-01-03 00:00:00| H;X| [H, X]|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]|
|2014-01-05 00:00:00| S;T;U| [S, T, U]|
|2014-01-06 00:00:00| G;C;G| [G, C, G]|
+-------------------+---------+---------------+
像這樣使用F.explode
分解list
列,
new_frame_exp = new_frame.withColumn("exp", F.explode('list'))
然后,您的 dataframe 將如下所示,
+-------------------+---------+---------------+---+
| date| flat| list|exp|
+-------------------+---------+---------------+---+
|2014-01-01 00:00:00| A;A;B| [A, A, B]| A|
|2014-01-01 00:00:00| A;A;B| [A, A, B]| A|
|2014-01-01 00:00:00| A;A;B| [A, A, B]| B|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| D|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| P|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| E|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| P|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| P|
|2014-01-03 00:00:00| H;X| [H, X]| H|
|2014-01-03 00:00:00| H;X| [H, X]| X|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| P|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| Q|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| G|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| S|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| T|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| U|
|2014-01-06 00:00:00| G;C;G| [G, C, G]| G|
|2014-01-06 00:00:00| G;C;G| [G, C, G]| C|
|2014-01-06 00:00:00| G;C;G| [G, C, G]| G|
+-------------------+---------+---------------+---+
在這個dataframe上,做一個groupBy這樣,
new_frame_exp_agg = new_frame_exp.groupBy('date', 'flat', 'list', 'exp').count()
然后你會有一個像這樣的dataframe,
+-------------------+---------+---------------+---+-----+
| date| flat| list|exp|count|
+-------------------+---------+---------------+---+-----+
|2014-01-03 00:00:00| H;X| [H, X]| H| 1|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| G| 1|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| U| 1|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| T| 1|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| P| 1|
|2014-01-03 00:00:00| H;X| [H, X]| X| 1|
|2014-01-06 00:00:00| G;C;G| [G, C, G]| G| 2|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| E| 1|
|2014-01-06 00:00:00| G;C;G| [G, C, G]| C| 1|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| S| 1|
|2014-01-01 00:00:00| A;A;B| [A, A, B]| B| 1|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| D| 1|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| Q| 1|
|2014-01-01 00:00:00| A;A;B| [A, A, B]| A| 2|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| P| 3|
+-------------------+---------+---------------+---+-----+
在這個 dataframe 上,再應用一層聚合來收集要列出的計數並像這樣找到最大值,
res = new_frame_exp_agg.groupBy('date', 'flat', 'list').agg(
F.collect_list('count').alias('occurances'),
F.max('count').alias('max'))
res.orderBy('date').show()
+-------------------+---------+---------------+----------+---+
| date| flat| list|occurances|max|
+-------------------+---------+---------------+----------+---+
|2014-01-01 00:00:00| A;A;B| [A, A, B]| [2, 1]| 2|
|2014-01-02 00:00:00|D;P;E;P;P|[D, P, E, P, P]| [1, 1, 3]| 3|
|2014-01-03 00:00:00| H;X| [H, X]| [1, 1]| 1|
|2014-01-04 00:00:00| P;Q;G| [P, Q, G]| [1, 1, 1]| 1|
|2014-01-05 00:00:00| S;T;U| [S, T, U]| [1, 1, 1]| 1|
|2014-01-06 00:00:00| G;C;G| [G, C, G]| [1, 2]| 2|
+-------------------+---------+---------------+----------+---+
如果您希望對列出現進行排序,如果您使用的是 spark occurance
,則可以在列上使用F.array_sort
,否則您必須為此編寫一個 udf。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.