Python 跨数据帧的行生成成对累积统计信息
我有一个包含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 ║ ╚══════════╩════╩═════╝ ╔══════════╦════╦═════╗ ║ 日期║ 身份证件║ 钥匙║ ╠══════════╬════╬═════╣ ║ 1/1/2018 ║ A.║ XY║ ║ 1/2/2018 ║ A.║ 燃气轮机║ ║ 1/6/2018 ║ A.║ 我们║ ║ 1/9/2018 ║ A.║ 人事军官║ ║ 1/2/2018 ║ B║ XY║ ║ 1/4/2018 ║ B║ 燃气轮机║ ╚══════════╩════╩═════╝ 输出: ╔══════════╦═══════════╦═══════╗ ║ FirstKey ║ SecondKey ║ Count ║ ╠══════════╬═══════════╬═══════╣ ║ XY ║ GT ║ 2 ║ ║ GT ║ WE ║ 1 ║ ║ WE ║ PO ║ 1 ║ ╚══════════╩═══════════╩═══════╝ ╔══════════╦═══════════╦═══════╗ ║ 一键║ 第二键║ 计数║ ╠══════════╬═══════════╬═══════╣ ║ XY║ 燃气轮机║ 2.║ ║ 燃气轮机║ 我们║ 1.║ ║ 我们║ 人事军官║ 1.║ ╚══════════╩═══════════╩═══════╝ 按ID排序,然后按日期排序,然后循环并构建计数,这将非常简单,但我希望你们中的一位大师能够帮助我将其构建得更并行/高效 基本上,因为是按日期排序的,所以我试图捕获键之间的时间转换数。对于ID=A,我们有XY,然后我们有GT(所以增加XY->GT乘以1)。然后我们将GT后跟we(因此将GT->PO增加1)Python 跨数据帧的行生成成对累积统计信息,python,scala,apache-spark,pyspark,Python,Scala,Apache Spark,Pyspark,我有一个包含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
使用scala/python处理spark。这里有一个潜在的解决方案,只需要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
这是一个可能的解决方案,只需要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
下面是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|
// +--------+---------+-----+
请注意,到日期的
转换是为了确保正确的时间顺序。这里是Scala中的一个解决方案,使用延迟(键,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|
// +--------+---------+-----+
请注意,到日期的转换是为了确保正确的时间顺序。您可以添加一个新列,显示由日期
使用排序的每个ID
的下一个键。然后按FirstKey
和SecondKey
分组,然后:
从pyspark.sql导入窗口
从pyspark.sql.functions导入col,lead
df.withColumn(“第二个键”,lead(“键”)。结束(Window.partitionBy(“ID”)。orderBy(“日期”))\
.where(col(“SecondKey”).isNotNull())\
.groupBy(col(“Key”)。别名(“FirstKey”),“SecondKey”)\
.count()\
.show()
#+--------+---------+-----+
#|第一键|第二键|计数|
#+--------+---------+-----+
#|WE|PO|1|
#|GT |我们| 1|
#|XY | GT | 2|
#+--------+---------+-----+
这假定Date
列是DateType
,因此可以对其进行适当的排序。如果它是一个字符串,您将不得不这样做,否则排序将按字典顺序进行 您可以使用添加一个新列,显示按日期排序的每个ID
的下一个键。然后按FirstKey
和SecondKey
分组,然后:
从pyspark.sql导入窗口
从pyspark.sql.functions导入col,lead
df.withColumn(“第二个键”,lead(“键”)。结束(Window.partitionBy(“ID”)。orderBy(“日期”))\
.where(col(“SecondKey”).isNotNull())\
.groupBy(col(“Key”)。别名(“FirstKey”),“SecondKey”)\
.count()\
.show()
#+--------+---------+-----+
#|第一键|第二键|计数|
#+--------+---------+-----+
#|WE|PO|1|
#|GT |我们| 1|
#|XY | GT | 2|
#+--------+---------+-----+
这假定Date
列是DateType
,因此可以对其进行适当的排序。如果它是一个字符串,您将不得不这样做,否则排序将按字典顺序进行 为什么id=A只需要6种可能的组合中的3种?@VamsiPrabhala我不太明白?我本可以用更好的措辞。基本上,因为是按日期排序的,所以我试图捕获键之间的时间转换数。对于ID=A,我们有XY,然后我们有GT(所以增加XY->GT乘以1)。然后我们将GT后跟we(因此将GT->PO增加1)。这说明了吗?为什么id=A只需要6种可能的组合中的3种?@VamsiPrabhala我不确定我是否理解?我本可以用更好的措辞。基本上,因为是按日期排序的,所以我试图捕获键之间的时间转换数。对于ID=A,我们有XY,然后我们有GT(所以增加XY->GT乘以1)。然后我们将GT后跟we(因此将GT->PO增加1)。这说明了吗?这个循环似乎正是我所认为的“直接”解决方案。不幸的是,我认为这并不是真正意义上的平行,不是吗?你是对的。然而,我只是想到了一个办法。我将立即编辑我的答案。这个循环似乎正是我所认为的“直接”解决方案。不幸的是,我认为这并不是真正意义上的平行,不是吗?你是对的。然而,我只是想到了一个办法。我会马上修改我的答案。