我有一个包含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。
答案 0 :(得分:2)
这是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
转换用于确保按时间顺序正确排序。
答案 1 :(得分:0)
这是一个仅需三行的潜在解决方案:
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
答案 2 :(得分:0)
您可以添加一个新列,以显示Key
使用pyspark.sql.functions.lead
排序的每个ID
的下一个Date
。然后按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
,因此可以适当地对其进行排序。如果是字符串,则必须convert it to a date,否则排序将按字典顺序进行。