Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.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 在PySpark中查找两个数据帧之间的更改_Python_Apache Spark_Pyspark - Fatal编程技术网

Python 在PySpark中查找两个数据帧之间的更改

Python 在PySpark中查找两个数据帧之间的更改,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,我有两个数据帧,比如说dfA和dfB dfA: IdCol | Col2 | Col3 id1 | val2 | val3 dfB: IdCol | Col2 | Col3 id1 | val2 | val4 这两个数据帧以IdCol形式连接。我希望每行比较它们,保持列不同,并在另一个数据帧中保留它们的值。例如,从上述两个数据帧中,我希望得到一个结果: dfChanges: RowId | Col | dfA_value | dfB_value | id1 | Col3

我有两个数据帧,比如说dfA和dfB

dfA:
IdCol | Col2  | Col3
id1   | val2  | val3

dfB:
IdCol | Col2  | Col3
id1   | val2  | val4
这两个数据帧以IdCol形式连接。我希望每行比较它们,保持列不同,并在另一个数据帧中保留它们的值。例如,从上述两个数据帧中,我希望得到一个结果:

dfChanges:
RowId | Col  | dfA_value | dfB_value |
id1   | Col3 | val_3     | val_4     |
我有点困在如何做这件事上了。有人能提供方向吗? 提前谢谢

编辑

我的尝试是这样的。但是它不是很清楚或者有很好的表现。有更好的方法吗

dfChanges = None

#for all column excpet id
for colName in dfA.column[1:]:

    #Select whole columns of id and targeted column 
    #from both datasets and subtract to find differences
    changedRows = dfA.select(['IdCol',colName]).subtract(dfB.select(['IdCol',colName]))

    #Join with dfB to take the value of targeted column from there
    temp = changedRows.join(dfB.select(col('IdCol'),col(colName).alias("dfB_value")),dfA.IdCol == dfB.IdCol, 'inner'). \
    drop(dfB.IdCol)

    #Proper Rename columns
    temp = temp.withColumnRenamed(colname,"dfA_value")
    temp = temp.withColumn("Col",lit(colName))

    #Append to a single dataframe
    if (dfChanges is None):
        dfChanges = temp
    else:
        dfChanges = dfChanges.union(temp)

按id连接两个数据帧:

dfA = spark.createDataFrame(
    [("id1", "val2", "val3")], ("Idcol1", "Col2", "Col3")
)

dfB = spark.createDataFrame(
    [("id1", "val2", "val4")], ("Idcol1", "Col2", "Col3")
)

dfAB = dfA.alias("dfA").join(dfB.alias("dfB"), "idCol1")
重塑:

from pyspark.sql.functions import col, struct

ids = ["Idcol1"]

vals = [struct(
    col("dfA.{}".format(c)).alias("dfA_value"),
    col("dfB.{}".format(c)).alias("dfB_value")
).alias(c) for c in dfA.columns if c not in ids]
melt
(定义)


这很好地工作,但我面临这个问题:当我的原始数据帧在列中有混合数据类型(例如,一个是整数,另一个是字符串)时,melt函数崩溃,无法解析数组异常。我目前将所有变量强制转换为字符串,但我认为这是不必要的。有没有修改melt函数以处理所有数据类型的建议?除了在melt函数中使用struct之外,我还应该使用其他数据类型吗?如果希望在单个表中进行所有更改,则需要使用单个类型。Spark使用关系模型,不支持联合类型。因此,如果输入是混合的,则必须强制转换。你们可以试着在熔化前比较数据,以避免不精确的问题。非常感谢,这真的很有帮助
(melt(dfAB.select(ids + vals), ids, [c for c in dfA.columns if c not in ids])
    .where(col("value.dfA_value") != col("value.dfB_value"))
    .select(ids + ["variable" , "value.dfA_value", "value.dfB_value"])
    .show())

+------+--------+---------+---------+                                           
|Idcol1|variable|dfA_value|dfB_value|
+------+--------+---------+---------+
|   id1|    Col3|     val3|     val4|
+------+--------+---------+---------+