Pyspark 使用Spark数据帧进行文本文件比较

Pyspark 使用Spark数据帧进行文本文件比较,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我想使用Spark dataframes实现以下要求,以比较2个文本/csv 列表项 档案。理想情况下,File1.txt应该与File2.txt进行比较,结果应该在另一个带有标志的txt文件中(相同的/UPDATE/INSERT/DELETE) 更新-如果与文件1相比,文件2中有任何记录值更新 插入-如果文件2中存在新记录 删除-仅当记录存在于文件1中时(不在文件2中) 相同-如果两个文件中存在相同的记录 File1.txt NO DEPT NAME SAL 1 IT RAM

我想使用Spark dataframes实现以下要求,以比较2个文本/csv

  • 列表项
档案。理想情况下,File1.txt应该与File2.txt进行比较,结果应该在另一个带有标志的txt文件中(相同的/UPDATE/INSERT/DELETE)

更新-如果与文件1相比,文件2中有任何记录值更新 插入-如果文件2中存在新记录 删除-仅当记录存在于文件1中时(不在文件2中) 相同-如果两个文件中存在相同的记录

File1.txt
NO  DEPT NAME   SAL 
1   IT  RAM     1000    
2   IT  SRI     600 
3   HR  GOPI    1500    
5   HW  MAHI    700 

File2.txt
NO  DEPT NAME   SAL 
1   IT   RAM    1000    
2   IT   SRI    900 
4   MT   SUMP   1200    
5   HW   MAHI   700

Outputfile.txt
NO  DEPT NAME    SAL   FLAG
1   IT  RAM     1000    S
2   IT  SRI     900     U
4   MT  SUMP    1200    I
5   HW  MAHI    700     S
3   HR  GOPI    1500    D
到目前为止,我做了下面的编码。但无法继续下去。请帮忙

from pyspark.shell import spark
sc = spark.sparkContext
df1 = spark.read.option("header","true").option("delimiter", ",").csv("C:\\inputs\\file1.csv")
df2 = spark.read.option("header","true").option("delimiter", ",").csv("C:\\inputs\\file2.csv")

df1.createOrReplaceTempView("table1")
df2.createOrReplaceTempView("table2")

sqlDF1 = spark.sql( "select * from table1" )
sqlDF2 = spark.sql( "select * from table2" )

leftJoinDF = sqlDF1.join(sqlDF2, 'id', how='left')
rightJoinDF = sqlDF1.join(sqlDF2, 'id', how='right')
innerJoinDF = sqlDF1.join(sqlDF2, 'id')
在执行leftJoin、rightJoin、innerJoin之后,如果我们合并数据,有什么方法吗。有了这个,我是否可以得到想要的输出或任何其他方式


谢谢,

您可以在下面找到我的解决方案。我为相同的/UPDATE/INSERT/DELETE案例创建了4个数据帧,然后将它们合并

>>从functools导入reduce
>>>从pyspark.sql导入数据帧
>>>导入pyspark.sql.F函数
>>>df1=sc.parallelize([
…(1,'IT','RAM',1000),
…(2,'IT','SRI',600),
…(3,'HR','GOPI',1500),
…(5,'HW','MAHI',700)
.toDF(['NO','DEPT','NAME','SAL'])
>>>df1.show()
+---+----+----+----+
|编号|部门|名称|萨尔|
+---+----+----+----+
|1 | IT | RAM | 1000|
|2 | IT | SRI | 600|
|3 | HR | GOPI | 1500|
|5 | HW | MAHI | 700|
+---+----+----+----+
>>>df2=sc.parallelize([
…(1,'IT','RAM',1000),
…(2,'IT','SRI',900),
…(4,'MT','SUMBOL',1200),
…(5,'HW','MAHI',700)
.toDF(['NO','DEPT','NAME','SAL'])
>>>df2.show()
+---+----+----+----+
|编号|部门|名称|萨尔|
+---+----+----+----+
|1 | IT | RAM | 1000|
|2 | IT | SRI | 900|
|4 | MT |集水坑| 1200|
|5 | HW | MAHI | 700|
+---+----+----+----+
#删除
>>>df_d=df1.join(df2,df1.NO==df2.NO,'left')。filter(F.isnull(df2.NO))。选择(df1.NO,df1.DEPT,df1.NAME,df1.SAL,F.lit('d')。别名('FLAG'))
#插入
>>>df_i=df1.join(df2,df1.NO==df2.NO,'right')。filter(F.isnull(df1.NO))。选择(df2.NO,df2.DEPT,df2.NAME,df2.SAL,F.lit('i')。别名('FLAG'))
#同样的/
>>>df_s=df1.join(df2,df1.NO==df2.NO,'internal').filter(F.concat(df2.NO,df2.DEPT,df2.NAME,df2.SAL)==F.concat(df1.NO,df1.DEPT,df1.NAME,df1.SAL))\
...     选择(df1.NO,df1.DEPT,df1.NAME,df1.SAL,F.lit('S')。别名('FLAG'))
#更新
>>>dfu=df1.join(df2,df1.NO==df2.NO,'internal').filter(F.concat(df2.NO,df2.DEPT,df2.NAME,df2.SAL)!=F.concat(df1.NO,df1.DEPT,df1.NAME,df1.SAL))\
...     选择(df2.NO、df2.DEPT、df2.NAME、df2.SAL、F.lit('U')。别名('FLAG'))
>>>dfs=[df_s,df_,df_,df_i]
>>>df=减少(DataFrame.unionAll,dfs)
>>> 
>>>df.show()
+---+----+----+----+----+                                                       
|无|部门|名称|萨尔|旗|
+---+----+----+----+----+
|5 | HW | MAHI | 700 | S|
|1 | IT | RAM | 1000 | S|
|2 | IT | SRI | 900 | U|
|2 | IT | SRI | 900 | U|
|4 | MT |集水坑| 1200 | I|
+---+----+----+----+----+

您可以在首先连接所有列之后使用
'outer'
连接。然后为标志创建一个
udf

导入pyspark.sql.F函数
df=sql.createDataFrame([
(1,'IT','RAM',1000),
(2,"IT","SRI",600),,
(3,'HR','GOPI',1500),
(5,"HW","MAHI",700),,
[‘否’、‘部门’、‘姓名’、‘萨尔’])
df1=sql.createDataFrame([
(1,'IT','RAM',1000),
(2,"IT","SRI",900),,
(4、‘MT’、‘集水坑’,1200),
(5,"HW","MAHI",700),,
[‘否’、‘部门’、‘姓名’、‘萨尔’])
def标志(x,y):
如果不是x:
返回y+'-I'
如果不是y:
返回x+'-D'
如果x==y:
返回x+'-S'
返回y+'-U'
_cols=df.columns
flag_udf=F.udf(lambda x,y:flags(x,y),StringType())
df=df.select(['NO']+[F.concat_ws('-',*[F.col(_c)表示df.columns中的_c])。别名('f1'))\
.join(df1.select(['NO']+[F.concat_ws('-',*[F.col('u c1)表示df1.columns中的[u c1])。别名('f2')),'NO','outer')\
.select(标志_udf('f1','f2')。别名('combined'))
df.show()
结果是,

+-------------+
|合二为一|
+----------------+
|5-HW-MAHI-700-S|
|1-IT-RAM-1000-S|
|3-HR-GOPI-1500-D|
|2-IT-SRI-900-U|
|4-MT-集水坑-1200-I|
+----------------+
最后,拆分
合并的

split\u col=F.split(df['combined'],'-')
df=df.select([split_col.getItem(i).枚举中i,s的别名([u cols+['FLAG']))
df.show()
你得到了想要的输出

+----+----+----++
|无|部门|名称|萨尔|旗|
+---+----+----+----+----+
|5 | HW | MAHI | 700 | S|
|1 | IT | RAM | 1000 | S|
|3 | HR | GOPI | 1500 | D|
|2 | IT | SRI | 900 | U|
|4 | MT |集水坑| 1200 | I|
+---+----+----+----+----+

感谢分享,但在上述最终结果中,我想确认两个澄清:1。记录(编号:2),重复两次。数据仅正确。对不起,我使用了df_两次。您应该用df_d更改第二个df_。它应该是dfs=[df_s,df_u,df_d,df_i]。我使用spark 2.3.0来尝试这个--df=df_d.union(df_I).union(df_s).union(df_u u)在df_s和df_u中进行concat时,如果(no,dept,name,sal)中有任何空值,则该记录不会出现在最终输出中。有没有办法过滤空值并将它们包含在合适的标志下。我尝试添加如下空条件:(df2.NO!='null',df2.DEPT!='null',df2.NAME!='null',df2.SAL!='null'),但问题仍然存在。