繁体   English   中英

跨数据帧行生成成对累积统计

[英]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 然后按FirstKeySecondKeycount

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM