[英]Generate Pair-wise Cumulative Stats Across Rows of Dataframe
我有一个包含3列的表格:日期,ID和键。 我希望找到一种有效的方法来对一个ID中的键的成对实例求和,然后与其他ID的总数相结合。 基本上建立时间过渡列表。 例如:
输入:
╔══════════╦════╦═════╗ ║ Date ║ ID ║ Key ║ ╠══════════╬════╬═════╣ ║ 1/1/2018 ║ A ║ XY ║ ║ 1/2/2018 ║ A ║ GT ║ ║ 1/6/2018 ║ A ║ WE ║ ║ 1/9/2018 ║ A ║ PO ║ ║ 1/2/2018 ║ B ║ XY ║ ║ 1/4/2018 ║ B ║ GT ║ ╚══════════╩════╩═════╝
输出:
╔══════════╦═══════════╦═══════╗ ║ FirstKey ║ SecondKey ║ Count ║ ╠══════════╬═══════════╬═══════╣ ║ XY ║ GT ║ 2 ║ ║ GT ║ WE ║ 1 ║ ║ WE ║ PO ║ 1 ║ ╚══════════╩═══════════╩═══════╝
按ID排序很简单,然后单击Date然后循环遍历并建立计数,但是我希望你们中的一位大师能够帮助我构建更并行/更高效的结构。
基本上,由于按日期排序,因此我试图捕获键之间的时间转换数。 因此,对于ID = A,我们有XY,然后有GT(所以XY-> GT递增1)。 然后我们有GT,然后是WE(因此,将GT-> PO加1)。
使用Scala / python处理Spark。
这是Scala中的一个解决方案,使用lag(Key, 1)
为密钥对计数配对上一个/当前密钥:
import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions.Window
import spark.implicits._
val df = Seq(
("1/1/2018", "A", "XY"),
("1/2/2018", "A", "GT"),
("1/6/2018", "A", "WE"),
("1/9/2018", "A", "PO"),
("1/2/2018", "B", "XY"),
("1/4/2018", "B", "GT")
).toDF("Date", "ID", "Key")
val win = Window.partitionBy("ID").orderBy("Date", "Key")
df.
withColumn("Date", to_date($"Date", "M/d/yyyy")).
withColumn("FirstKey", lag($"Key", 1).over(win)).
groupBy($"FirstKey", $"Key".as("SecondKey")).agg(count("*").as("Count")).
where($"firstKey".isNotNull).
show
// +--------+---------+-----+
// |FirstKey|SecondKey|Count|
// +--------+---------+-----+
// | WE| PO| 1|
// | GT| WE| 1|
// | XY| GT| 2|
// +--------+---------+-----+
请注意, to_date
转换用于确保正确的时间顺序。
这是一个仅需3条线的潜在解决方案:
import pandas as pd
df = pd.DataFrame({'Date': ['1/1/2018', '1/2/2018', '1/6/2018', '1/9/2018', '1/2/2018', '1/4/2018'], 'ID': ['A', 'A', 'A', 'A', 'B', 'B'], 'Key': ['XY', 'GT', 'WE', 'PO', 'XY', 'GT']})
print(df)
Date ID Key
0 1/1/2018 A XY
1 1/2/2018 A GT
2 1/6/2018 A WE
3 1/9/2018 A PO
4 1/2/2018 B XY
5 1/4/2018 B GT
df['key_lag'] = df.Key.shift(-1)
df['key_pairs'] = df.Key + ' ' + df.key_lag
print(df.groupby('key_pairs').size())
key_pairs
GT WE 1
PO XY 1
WE PO 1
XY GT 2
dtype: int64
您可以使用pyspark.sql.functions.lead
添加新列,以显示按Date
排序的每个ID
的下一个Key
。 然后按FirstKey
和SecondKey
并count
:
from pyspark.sql import Window
from pyspark.sql.functions import col, lead
df.withColumn("SecondKey", lead("Key").over(Window.partitionBy("ID").orderBy("Date")))\
.where(col("SecondKey").isNotNull())\
.groupBy(col("Key").alias("FirstKey"), "SecondKey")\
.count()\
.show()
#+--------+---------+-----+
#|FirstKey|SecondKey|count|
#+--------+---------+-----+
#| WE| PO| 1|
#| GT| WE| 1|
#| XY| GT| 2|
#+--------+---------+-----+
假定Date
列是DateType
以便可以对其进行适当排序。 如果是字符串,则必须将其转换为日期,否则排序将按字典顺序进行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.