Apache spark Pyspark数据帧:查找两个数据帧(值和列名)之间的差异

Apache spark Pyspark数据帧:查找两个数据帧(值和列名)之间的差异,apache-spark,pyspark,apache-spark-sql,spark-dataframe,pyspark-sql,Apache Spark,Pyspark,Apache Spark Sql,Spark Dataframe,Pyspark Sql,我在dataframe中总共有100多列。 我试图比较两个数据帧,并找到列名不匹配的记录。 我得到一个下面的输出代码,但当我运行100+列的代码时,作业被中止 我这样做是为了SCD类型2增量进程错误查找 从pyspark.sql.types导入* 从pyspark.sql.functions导入* d2=sc.并行化([(“A1”,5001005),(“A2”,70010007)]) dataFrame1=sqlContext.createDataFrame(d2、[“ID”、“VALUE1”、

我在dataframe中总共有100多列。 我试图比较两个数据帧,并找到列名不匹配的记录。 我得到一个下面的输出代码,但当我运行100+列的代码时,作业被中止

我这样做是为了SCD类型2增量进程错误查找

从pyspark.sql.types导入*
从pyspark.sql.functions导入*
d2=sc.并行化([(“A1”,5001005),(“A2”,70010007)])
dataFrame1=sqlContext.createDataFrame(d2、[“ID”、“VALUE1”、“VALUE2”])
d2=sc.并行化([(“A1”,6001005),(“A2”,70010007)])
dataFrame2=sqlContext.createDataFrame(d2、[“ID”、“VALUE1”、“VALUE2”])
key\u id\u col\u name=“id”
key\u id\u value=“A1”
dataFrame1.select(“ID”、“VALUE1”).subtract(dataFrame2.select(“ID”、col(“VALUE1”).alias(“value”)).show()
def unequalColumnValuesTwoDF(数据框1、数据框2、键id列名称、键id值):
chk_fst=真
dataFrame1=dataFrame1.where(dataFrame1[key\u id\u col\u name]==key\u id\u值)
dataFrame2=dataFrame2.where(dataFrame2[key\u id\u col\u name]==key\u id\u值)
col_names=list(set(dataFrame1.columns).交集(dataFrame2.columns))
列名称。删除(键id列名称)
对于col_名称中的col_名称:
如果chk_fst==真:
df_tmp=dataFrame1.select(col(key_id_col_name)。alias(“key_id”)、col(col_name)。alias(“VALUE”)。subtract(dataFrame2.select(col(key_id_col_name)。alias(“key_id”)、col(col_name)。alias(“VALUE”)。with column(“col_name”)、lit(col_name))
chk_fst=错误
其他:
df_tmp=df_tmp.unionAll(dataFrame1.select(col(key_id_col_name)、alias(key_id)、col(col_name)、alias(col_name)、alias(VALUE))。减去(dataFrame2.select(col(key_id_col_name)、alias(key_id)、col(col_name)、alias(VALUE))。带列(col_name)、lit(col_name)))
返回df_tmp
res\u df=unequalColumnValuesTwoDF(dataFrame1,dataFrame2,key\u id\u col\u name,key\u id\u value)
res_df.show()
>>>dataFrame1.show()
+---+------+------+
|ID |值1 |值2|
+---+------+------+
|A1 | 500 | 1005|
|A2 | 700 | 10007|
+---+------+------+
>>>dataFrame2.show()
+---+------+------+
|ID |值1 |值2|
+---+------+------+
|A1 | 600 | 1005|
|A2 | 700 | 10007|
+---+------+------+
>>>res_df.show()
+------+-----+--------+
|键| ID |值|列|名称|
+------+-----+--------+
|A1 | 500 |值1|
+------+-----+--------+

请建议其他方法。

这里是另一种方法:

  • 使用
    ID
    列连接两个数据帧
  • 然后,为每一行创建一个新列,其中包含有差异的列。
    • 使用.1将此新列创建为键值对映射
    • 映射的键将是列名
    • 使用,将值设置为
      dataFrame1
      中的相应值(因为这似乎是您在示例中想要的)如果两个数据帧之间存在差异。否则,我们将该值设置为
      None
  • 在map列上使用,并使用筛选出差异不为null的所有行
  • 选择所需的列并使用
    alias()
    重命名
例如:

导入pyspark.sql.f函数
columns=[c代表dataFrame1中的c.columns如果c!=“ID”]
dataFrame1.alias('r').join(dataFrame2.alias('l'),on='ID'))\
.withColumn(
"差异",,
f、 创建地图(
*减少(
列表。添加,
[
[
f、 lit(c),
f、 什么时候(
f、 col('r.+c)!=f.col('l.+c)、,
f、 柱(r.+c)
)。否则(无)
] 
对于列中的c
]
)
)
)\
.选择([f.col('ID')、f.explode('diff'))\
.where(~f.isnull(f.col('value'))\
.选择(
f、 col('ID')。别名('KEY_ID'),
f、 列('value')。别名('value'),
f、 col('key')。别名('col_NAME'))
)\
.show(truncate=False)
#+------+-----+--------+
#|键| ID |值|列|名称|
#+------+-----+--------+
#|A1 | 500 |值1|
#+------+-----+--------+
注释

1语法
*reduce(list.\uu add\uu,[[f.lit(c),…]表示列中的c])
作为
create\u map()
的参数是一些帮助动态创建映射的python fu

create\u map()
需要偶数个参数-它假定每对中的第一个参数是键,第二个是值。为了按该顺序放置参数,列表理解为每个迭代生成一个列表。我们使用
list.\uuuu add\uuuuu
将此列表缩减为一个平面列表

最后,使用
*
操作符来解包列表

这是中间输出,可以使逻辑更清晰:

dataFrame1.alias('r').join(dataFrame2.alias('l'),on='ID'))\
.withColumn(
"差异",,
f、 创建地图(
*减少(
列表。添加,
[
[
f、 lit(c),
f、 什么时候(
f、 col('r.+c)!=f.col('l.+c)、,
f、 柱(r.+c)
)。否则(无)
] 
对于列中的c
]
)
)
)\
.select('ID','diff').show(truncate=False)
#+---+-----------------------------------+
#|ID | diff|
#+---+-----------------------------------+
#|A2 |映射(VALUE1->null,VALUE2->null)|
#|A1 |映射(值1->500,值2->null)|
#+---+-----------------------------------+

以下是另一种方法:

  • 使用
    ID
    列连接两个数据帧
  • 然后,为每一行创建一个新列,该列