按列中的相似名称对行进行分组
Group rows by similar name in column
为了计算,我已经创建了这个数据框
df1:
+--------------+------+------------+
|name |MG |questions |
+--------------+------+------------+
|toto |MG1 |[Q1, Q2] |
|toto |MG3 |[Q4, Q6, Q7]|
|toto-123 |MG1 |[Q1, Q2] |
|toto-456 |MG1 |[Q1, Q2] |
|titi |MG1 |[Q1, Q2] |
|... |... |... |
+--------------+------+------------+
到现在为止,这已经足够了,但是现在,为了新的需要,我遇到了一个我没有解决的问题:我必须按 name
和 MG
对行进行分组,而不是确切的 name
,但与 name
相似,就像那样
df1:
+--------------+------+-----------------------------+
|name |MG |questions |
+--------------+------+-----------------------------+
|toto |MG1 |[Q1, Q2] [Q1, Q2] [Q1, Q2] |
|toto |MG3 |[Q4, Q6, Q7] |
|titi |MG1 |[Q1, Q2] |
|... |... |... |
+--------------+------+-----------------------------+
这里,toto的questions
是toto, toto-123 and toto-456
的问题。它们可以位于不同的阵列中,也可以位于同一阵列中。理想情况下,toto-123
和 toto-456
的行仍然保留。
我尝试了 groupby
带有条件思想 SQL 表达式的函数,但没有成功
你有什么提示或解决办法吗?
非常感谢
您可以先使用自连接查找具有相似 name
和 mg
值的行,在连接条件中使用 like
运算符:
import pyspark.sql.functions as F
df = spark.createDataFrame([
("toto", "MG1", ["Q1", "Q2"]), ("toto", "MG3", ["Q4", "Q6", "Q7"]),
("toto-123", "MG1", ["Q1", "Q2"]), ("toto-456", "MG1", ["Q1", "Q2"]),
("titi", "MG1", ["Q1", "Q2"])], ["name", "mg", "questions"])
similar_df = df.alias("a").join(
df.alias("b"),
F.expr("a.name like concat('%', b.name, '%') and a.mg = b.mg and a.name != b.name"),
).selectExpr("a.name", "a.mg", "b.name as similar_name")
similar_df.show()
#+--------+---+------------+
#| name| mg|similar_name|
#+--------+---+------------+
#|toto-123|MG1| toto|
#|toto-456|MG1| toto|
#+--------+---+------------+
然后,再次与原始dataframe合并,并将对应名称的值更改为第一步找到的相似名称,最后按name
和mg
分组,收集[=的列表17=]:
result = df.alias("df").join(
similar_df.alias("s"),
["name", "mg"],
'left'
).select(
F.coalesce(F.col("similar_name"), F.col("df.name")).alias("name"),
F.col("mg"),
F.col("df.questions"),
).groupBy("name", "mg").agg(
F.collect_list("questions").alias("questions")
)
result.show(truncate=False)
#+----+---+------------------------------+
#|name|mg |questions |
#+----+---+------------------------------+
#|toto|MG1|[[Q1, Q2], [Q1, Q2], [Q1, Q2]]|
#|titi|MG1|[[Q1, Q2]] |
#|toto|MG3|[[Q4, Q6, Q7]] |
#+----+---+------------------------------+
为了计算,我已经创建了这个数据框
df1:
+--------------+------+------------+
|name |MG |questions |
+--------------+------+------------+
|toto |MG1 |[Q1, Q2] |
|toto |MG3 |[Q4, Q6, Q7]|
|toto-123 |MG1 |[Q1, Q2] |
|toto-456 |MG1 |[Q1, Q2] |
|titi |MG1 |[Q1, Q2] |
|... |... |... |
+--------------+------+------------+
到现在为止,这已经足够了,但是现在,为了新的需要,我遇到了一个我没有解决的问题:我必须按 name
和 MG
对行进行分组,而不是确切的 name
,但与 name
相似,就像那样
df1:
+--------------+------+-----------------------------+
|name |MG |questions |
+--------------+------+-----------------------------+
|toto |MG1 |[Q1, Q2] [Q1, Q2] [Q1, Q2] |
|toto |MG3 |[Q4, Q6, Q7] |
|titi |MG1 |[Q1, Q2] |
|... |... |... |
+--------------+------+-----------------------------+
这里,toto的questions
是toto, toto-123 and toto-456
的问题。它们可以位于不同的阵列中,也可以位于同一阵列中。理想情况下,toto-123
和 toto-456
的行仍然保留。
我尝试了 groupby
带有条件思想 SQL 表达式的函数,但没有成功
你有什么提示或解决办法吗? 非常感谢
您可以先使用自连接查找具有相似 name
和 mg
值的行,在连接条件中使用 like
运算符:
import pyspark.sql.functions as F
df = spark.createDataFrame([
("toto", "MG1", ["Q1", "Q2"]), ("toto", "MG3", ["Q4", "Q6", "Q7"]),
("toto-123", "MG1", ["Q1", "Q2"]), ("toto-456", "MG1", ["Q1", "Q2"]),
("titi", "MG1", ["Q1", "Q2"])], ["name", "mg", "questions"])
similar_df = df.alias("a").join(
df.alias("b"),
F.expr("a.name like concat('%', b.name, '%') and a.mg = b.mg and a.name != b.name"),
).selectExpr("a.name", "a.mg", "b.name as similar_name")
similar_df.show()
#+--------+---+------------+
#| name| mg|similar_name|
#+--------+---+------------+
#|toto-123|MG1| toto|
#|toto-456|MG1| toto|
#+--------+---+------------+
然后,再次与原始dataframe合并,并将对应名称的值更改为第一步找到的相似名称,最后按name
和mg
分组,收集[=的列表17=]:
result = df.alias("df").join(
similar_df.alias("s"),
["name", "mg"],
'left'
).select(
F.coalesce(F.col("similar_name"), F.col("df.name")).alias("name"),
F.col("mg"),
F.col("df.questions"),
).groupBy("name", "mg").agg(
F.collect_list("questions").alias("questions")
)
result.show(truncate=False)
#+----+---+------------------------------+
#|name|mg |questions |
#+----+---+------------------------------+
#|toto|MG1|[[Q1, Q2], [Q1, Q2], [Q1, Q2]]|
#|titi|MG1|[[Q1, Q2]] |
#|toto|MG3|[[Q4, Q6, Q7]] |
#+----+---+------------------------------+