我有一个DataFrame,我在下面粘贴数据:
+---------------+--------------+----------+------------+----------+
|name | DateTime| Seq|sessionCount|row_number|
+---------------+--------------+----------+------------+----------+
| abc| 1521572913344| 17| 5| 1|
| xyz| 1521572916109| 17| 5| 2|
| rafa| 1521572916118| 17| 5| 3|
| {}| 1521572916129| 17| 5| 4|
| experience| 1521572917816| 17| 5| 5|
+---------------+--------------+----------+------------+----------+
列'name'
的类型为字符串。我想要一个新列"effective_name"
,其中包含"name"
的增量值,如下所示:
+---------------+--------------+----------+------------+----------+-------------------------+
|name | DateTime |sessionSeq|sessionCount|row_number |effective_name|
+---------------+--------------+----------+------------+----------+-------------------------+
|abc |1521572913344 |17 |5 |1 |abc |
|xyz |1521572916109 |17 |5 |2 |abcxyz |
|rafa |1521572916118 |17 |5 |3 |abcxyzrafa |
|{} |1521572916129 |17 |5 |4 |abcxyzrafa{} |
|experience |1521572917816 |17 |5 |5 |abcxyzrafa{}experience |
+---------------+--------------+----------+------------+----------+-------------------------+
新列包含其先前name
列值的增量串联。
答案 0 :(得分:1)
您可以使用pyspark.sql.Window
按clientDateTime
,pyspark.sql.functions.concat_ws
和pyspark.sql.functions.collect_list
排序来实现此目的:
import pyspark.sql.functions as f
from pyspark.sql import Window
w = Window.orderBy("DateTime") # define Window for ordering
df.drop("Seq", "sessionCount", "row_number").select(
"*",
f.concat_ws(
"",
f.collect_list(f.col("name")).over(w)
).alias("effective_name")
).show(truncate=False)
#+---------------+--------------+-------------------------+
#|name | DateTime|effective_name |
#+---------------+--------------+-------------------------+
#|abc |1521572913344 |abc |
#|xyz |1521572916109 |abcxyz |
#|rafa |1521572916118 |abcxyzrafa |
#|{} |1521572916129 |abcxyzrafa{} |
#|experience |1521572917816 |abcxyzrafa{}experience |
#+---------------+--------------+-------------------------+
我放弃了"Seq"
,"sessionCount"
,"row_number"
以使输出显示更友好。
如果您需要为每个组执行此操作,则可以向partitionBy
添加Window
。在这种情况下,您希望按sessionSeq
进行分组,您可以执行以下操作:
w = Window.partitionBy("Seq").orderBy("DateTime")
df.drop("sessionCount", "row_number").select(
"*",
f.concat_ws(
"",
f.collect_list(f.col("name")).over(w)
).alias("effective_name")
).show(truncate=False)
#+---------------+--------------+----------+-------------------------+
#|name | DateTime|sessionSeq|effective_name |
#+---------------+--------------+----------+-------------------------+
#|abc |1521572913344 |17 |abc |
#|xyz |1521572916109 |17 |abcxyz |
#|rafa |1521572916118 |17 |abcxyzrafa |
#|{} |1521572916129 |17 |abcxyzrafa{} |
#|experience |1521572917816 |17 |abcxyzrafa{}experience |
#+---------------+--------------+----------+-------------------------+
如果您更喜欢使用withColumn
,则上述内容相当于:
df.drop("sessionCount", "row_number").withColumn(
"effective_name",
f.concat_ws(
"",
f.collect_list(f.col("name")).over(w)
)
).show(truncate=False)
<强>解释强>
您希望在多行上应用函数,这称为聚合。使用任何聚合,您需要定义要聚合的行和顺序。我们使用Window
执行此操作。在这种情况下,w = Window.partitionBy("Seq").orderBy("DateTime")
会按Seq
对数据进行分区,并按DateTime
排序。
我们首先在窗口上应用聚合函数collect_list("name")
。这会收集name
列中的所有值,并将它们放在列表中。插入顺序由Window的顺序定义。
例如,此步骤的中间输出将是:
df.select(
f.collect_list("name").over(w).alias("collected")
).show()
#+--------------------------------+
#|collected |
#+--------------------------------+
#|[abc] |
#|[abc, xyz] |
#|[abc, xyz, rafa] |
#|[abc, xyz, rafa, {}] |
#|[abc, xyz, rafa, {}, experience]|
#+--------------------------------+
既然列表中有适当的值,我们可以将它们连接在一起,并将空字符串作为分隔符。
df.select(
f.concat_ws(
"",
f.collect_list("name").over(w)
).alias("concatenated")
).show()
#+-----------------------+
#|concatenated |
#+-----------------------+
#|abc |
#|abcxyz |
#|abcxyzrafa |
#|abcxyzrafa{} |
#|abcxyzrafa{}experience |
#+-----------------------+
答案 1 :(得分:0)
<强>解决方案:强>
将pyspark.sql.functions导入为f
w = Window.partitionBy(&#34; Seq&#34;)。orderBy(&#34; DateTime&#34;)
df.select( &#34; *&#34 ;, f.concat_ws( &#34;&#34 ;, f.collect_set(f.col(&#34;名称&#34))。在(w)的 ).alias(&#34; cummuliative_name&#34) ).show()
<强>解释强>
collect_set() - 此函数返回的值类似于[[&#34; abc&#34;,&#34; xyz&#34;,&#34; rafa&#34;,{},&#34;经验&# 34;]]。
concat_ws() - 此函数将collect_set()的输出作为输入并将其转换为abc,xyz,rafa,{},体验
注意:强> 如果您没有重复项,请使用 collect_set(),否则请使用 collect_list()