我需要创建一个event_id,基本上是在多个列(v_id,d_id,ip,l_id)上进行计数器分组,并在delta> gt时递增它。 40来得到 像这样的输出
v_id d_id ip l_id delta event_id last_event_flag 1 20 30 40 1 1 N 1 20 30 40 2 1 N 1 20 30 40 3 1 N 1 20 30 40 4 1 Y 1 20 20 40 1 1 Y 1 30 30 40 2 1 N 1 30 30 40 3 1 N 1 30 30 40 4 1 N 1 30 30 40 5 1 Y
我能够使用pandas数据框实现这一目标
df['event_id'] = (df.delta >=40.0).groupby([df.l_id,df.v_id,d_id,ip]).cumsum() + 1
df.append(df['event_id'], ignore_index=True
但在更大的数据上执行时会看到内存错误。
如何在pyspark中做类似的事情。
答案 0 :(得分:1)
在pyspark中,您可以使用window
函数执行此操作:
首先让我们创建数据帧。请注意,您也可以直接从csv:
将其作为数据框加载df = spark.createDataFrame(
sc.parallelize(
[[1,20,30,40,1,1],
[1,20,30,40,2,1],
[1,20,30,40,3,1],
[1,20,30,40,4,1],
[1,20,30,40,45,2],
[1,20,30,40,1,2],
[1,30,30,40,2,1],
[1,30,30,40,3,1],
[1,30,30,40,4,1],
[1,30,30,40,5,1]]
),
["v_id","d_id","ip","l_id","delta","event_id"]
)
你的表中有一个隐式排序,我们需要创建一个单调递增的id,这样我们就不会最终改变它了:
import pyspark.sql.functions as psf
df = df.withColumn(
"rn",
psf.monotonically_increasing_id()
)
+----+----+---+----+-----+--------+----------+
|v_id|d_id| ip|l_id|delta|event_id| rn|
+----+----+---+----+-----+--------+----------+
| 1| 20| 30| 40| 1| 1| 0|
| 1| 20| 30| 40| 2| 1| 1|
| 1| 20| 30| 40| 3| 1| 2|
| 1| 20| 30| 40| 4| 1| 3|
| 1| 20| 30| 40| 45| 2| 4|
| 1| 20| 30| 40| 1| 2|8589934592|
| 1| 30| 30| 40| 2| 1|8589934593|
| 1| 30| 30| 40| 3| 1|8589934594|
| 1| 30| 30| 40| 4| 1|8589934595|
| 1| 30| 30| 40| 5| 1|8589934596|
+----+----+---+----+-----+--------+----------+
现在计算event_id
和last_event_flag
:
from pyspark.sql import Window
w1 = Window.partitionBy("v_id", "d_id", "l_id", "ip").orderBy("rn")
w2 = Window.partitionBy("v_id", "d_id", "l_id", "ip").orderBy(psf.desc("rn"))
df.withColumn(
"event_id",
psf.sum((df.delta >= 40).cast("int")).over(w1) + 1
).withColumn(
"last_event_flag",
psf.row_number().over(w2) == 1
).drop("rn")
+----+----+---+----+-----+--------+---------------+
|v_id|d_id| ip|l_id|delta|event_id|last_event_flag|
+----+----+---+----+-----+--------+---------------+
| 1| 20| 30| 40| 1| 1| false|
| 1| 20| 30| 40| 2| 1| false|
| 1| 20| 30| 40| 3| 1| false|
| 1| 20| 30| 40| 4| 1| false|
| 1| 20| 30| 40| 45| 2| false|
| 1| 20| 30| 40| 1| 2| true|
| 1| 30| 30| 40| 2| 1| false|
| 1| 30| 30| 40| 3| 1| false|
| 1| 30| 30| 40| 4| 1| false|
| 1| 30| 30| 40| 5| 1| true|
+----+----+---+----+-----+--------+---------------+
答案 1 :(得分:0)
也许你应该在运行groupby之前计算df = df [df.delta> = 40] - 我不确定这是否重要。
此外,您可以查看chunksize以基于csv的块执行计算以获得内存效率。因此,您可以将数据拆分为10000行的块,然后运行计算以避免内存错误。
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html