Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用搜索和条件查找两列值之间的差异_Python_Pyspark_Pyspark Sql - Fatal编程技术网

Python 使用搜索和条件查找两列值之间的差异

Python 使用搜索和条件查找两列值之间的差异,python,pyspark,pyspark-sql,Python,Pyspark,Pyspark Sql,在pyspark中,我有一个如下所示的数据帧,其中的行根据id和k1的值进行排序。此外,每行都有一个唯一的递增编号(rowid) ----------------------- rowid | id | k1 | k2| ----------------------- 1 | 1 | v1 | l1| 2 | 1 | v1 | v1| 3 | 1 | v1 | l2| 4 | 2 | v2 | v2| 5 | 2 | v2 | l3| 6 | 3 | v3 | l3| -------------

在pyspark中,我有一个如下所示的数据帧,其中的行根据id和k1的值进行排序。此外,每行都有一个唯一的递增编号(rowid)

-----------------------
rowid | id | k1 | k2|
-----------------------
1 | 1 | v1 | l1|
2 | 1 | v1 | v1|
3 | 1 | v1 | l2|
4 | 2 | v2 | v2|
5 | 2 | v2 | l3|
6 | 3 | v3 | l3|
----------------------
对于id的每个唯一值,我想计算其中k1==k2的第一行的rowid与观察到id为+1的记录的第一行对应的rowid之间的差值,并将结果存储在一个新列(即秩)中。 输出应该如下所示

----------------
id | k1 |等级|
-----------------
1 | v1 | 2|
2 | v2 | 1|
3 | v3 | 0 |
-----------------
e、 例如,对于id=1,当rowid=2时k1==k2的值。当rowid=1时,第一次观察到id=1。将2-1+1=2放入秩列。对于id=3,我们没有任何列k1和k2的值匹配的记录。因此,用0(或null)填充秩列


我假设这涉及基于id的groupBy,但我不确定如何获取与列k1和k2匹配的行对应的索引以及与每个唯一id对应的第一个rowid。

首先创建一个示例数据帧

导入pyspark.sql.F函数
从pyspark.sql.types导入*
df=sql.createDataFrame([
(1,1,'v1','l1'),
(2,1,'v1','v1'),
(3,1,'v1','l2'),
(4,2,'v2','v2'),
(5,2,'v2','l3'),
(6,3,'v3','l3'),
],[
“rowid”、“id”、“k1”、“k2'])
然后创建一个udf并将其应用于列

def get_rank_udf(行):
行=已排序(行,键=lambda x:x['rowid'])
第一行\u id=行[0]['rowid']
对于行中的_r:
如果r['k1']==\r['k2']:
相等的行id=\r['rowid']
打破
其他:
相等的行id=无
如果equal_row_id为None:
返回0
返回相等的行id-第一行id+1
get\u rank=F.udf(lambda x:get\u rank\u udf(x),IntegerType())
df=df.groupby('id','k1').agg(F.collect_list(F.struct('rowid','k1','k2'))。别名('elements'))\
.withColumn('rank',get_rank(F.col('elements'))\
.选择('id','k1','rank')
这就给出了输出

+--+--+--+
|id | k1 |等级|
+---+---+----+
|1 | v1 | 2|
|2 | v2 | 1|
|3 | v3 | 0|
+---+---+----+

您可以使用API函数在
id
k1
上使用
groupBy
来执行此操作,这应该是:

导入pyspark.sql.f函数
df.groupBy(“id”、“k1”)\
阿格先生(
f、 最小值(f.when(f.col(“k1”)==f.col(“k2”)、f.col(“rowid”))。别名(“第一个相等”),
f、 min(“rowid”).别名(“第一行”)
)\
。选择(“id”、“k1”),(f.col(“第一行”)-f.col(“第一行”)+1)。别名(“排名”))\
.fillna(0)\
.show()
#+---+---+----+
#|id | k1 |等级|
#+---+---+----+
#|1 | v1 | 2|
#|2 | v2 | 1|
#|3 | v3 | 0|
#+---+---+----+
rank
的计算可分为两个聚合步骤:

  • 第一次聚合为每个
    id
    k1
    对取其
    k1==k2
    的min
    rowid
  • 第二个聚合在每个
    id
    k1
    对上获取min
    rowid
您可以根据您的要求取这些值的差值(
+1
),最后用
0
填充任何
null


更新:使用
行号的替代方法

从pyspark.sql导入窗口
#您可以按列定义自己的顺序
w=Window.partitionBy(“id”,“k1”).orderBy(“rowid”)
df.withColumn(“秩”,f.when(f.expr(“k1=k2”),f.row_number(),over(w)))\
.groupBy(“id”、“k1”)\
.agg(f.min(“排名”))\
.fillna(0)\
.show()
#同上

谢谢,我也可以按如下方式解决这个问题,但您的解决方案更优雅:)您知道哪一个更有效吗?我是说加入对udf
df2=df.groupBy(“id”).agg(fn.min(“rowid”).alias(“minRowId”)
rank=df.join(df2,df.id==df2.id,how='full')。drop(df2.id)
rank=rank.withColumn(“diff”,fn.当(fn.col(“k1”)==fn.col(“k2”),rank.rowid-rank.minRowId+1”)
udf
。这取决于你喜欢什么。漂亮!!如果
rowid
列不可用,您能想出一种方法吗?我故意添加了这个,因为我认为这会使问题变得容易。@user3192082是您要找的吗?我不确定我是否理解。我已经习惯于为每一行指定一个顺序索引。我的意思是,如果我想避免这种情况(即数据帧没有rowid列),我们仍然可以解决这个问题并计算排名吗?@user3192082是的,如果您有办法对每个组中的行进行排序。根据你提供的数据,我看不出一个明显的方法。例如,对于
id=1
,为什么
l1
v1
之前排序,在
l2
之前排序?如果有办法对它们进行排序,您可以使用
pyspark.sql.functions.rank
pyspark.sql.functions.row\u number
@user3192082我添加了一个编辑,向您展示了如何进行排序的示例。您必须定义窗口函数,以便以适当的方式对行进行排序。这里我使用的是
rowid
,但是您可以使用任何您喜欢的方法。(请记住,spark数据帧本质上是无序的,因此不容易依赖数据在源系统中的显示顺序)。