【问题标题】:Comparing schema of dataframe using Pyspark使用 Pyspark 比较数据框的模式
【发布时间】:2018-07-18 07:12:48
【问题描述】:

我有一个数据框 (df)。 为了显示我使用的架构:

from pyspark.sql.functions import *
df1.printSchema()

我得到以下结果:

#root
# |-- name: string (nullable = true)
# |-- age: long (nullable = true)

有时架构会改变(列类型或名称):

df2.printSchema()


 #root
        # |-- name: array (nullable = true)
        # |-- gender: integer (nullable = true)
        # |-- age: long (nullable = true)

我想比较两种模式(df1df2),并只获取类型和列名的差异(有时列可以移动到另一个位置)。 结果应该是这样的表格(或数据框):

   column                df1          df2     diff                       
    name:               string       array     type                             
    gender:              N/A         integer   new column 

(age栏目相同,没有变化。如果栏目遗漏,会有提示'omitted') 如果我每列有很多列,我该如何高效地做到这一点?

【问题讨论】:

  • 它缺少您尝试过的解决方案...

标签: python apache-spark pyspark apache-spark-sql


【解决方案1】:

没有任何外部库,我们可以使用找到架构差异

from pyspark.sql.session import SparkSession
from pyspark.sql import DataFrame

def schema_diff(spark: SparkSession, df_1: DataFrame, df_2: DataFrame):
    s1 = spark.createDataFrame(df_1.dtypes, ["d1_name", "d1_type"])
    s2 = spark.createDataFrame(df_2.dtypes, ["d2_name", "d2_type"])
    difference = (
        s1.join(s2, s1.d1_name == s2.d2_name, how="outer")
        .where(s1.d1_type.isNull() | s2.d2_type.isNull())
        .select(s1.d1_name, s1.d1_type, s2.d2_name, s2.d2_type)
        .fillna("")
    )
    return difference

  • fillna 是可选的。我更喜欢将它们视为空字符串。
  • 在 where 子句中我们使用类型,因为这将帮助我们显示列是否存在于两个数据框中,但它们具有不同的架构。
  • 这还将显示在第二个数据帧中但不在第一个数据帧中的所有列

用法:

diff = schema_diff(spark, df_1, df_2)
diff.show(diff.count(), truncate=False)

【讨论】:

  • 这不会检测类型差异,因为连接条件仅使用列名。它应该是(s1["d1_name"] == s2["d2_name"]) & (s1["d1_type"] == s2["d2_type"])
  • @blackbishop 上述函数的目的是显示差异。目的不是过滤掉奇怪的。因此,输出差异数据帧将包含所有详细信息(s1.d1_name、s1.d1_type、s2.d2_name、s2.d2_type),因此该函数的使用者可以为所欲为。
  • 好的,在这种情况下,您应该删除 where 子句,否则它不会返回名称相同但类型不同的列。用这些数据框试试吧:df1 = spark.createDataFrame([("a", (1, 2))], "a: string, b struct<x:int,y:int>"), df2 = spark.createDataFrame([("a", (1, 2))], "a: string, b struct<z:int,t:int>")
【解决方案2】:

你可以简单地使用

df1.printSchema() == df2.printSchema()

【讨论】:

【解决方案3】:

您可以尝试使用来自 DF1 和 DF2 的元数据创建两个 pandas 数据帧,如下所示

pd_df1=pd.DataFrame(df1.dtypes,columns=['column','data_type'])
pd_df2=pd.DataFrame(df2.dtypes,columns=['column','data_type'])

然后通过 'outer' join 加入这两个 pandas 数据帧?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-02
    • 2020-12-22
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 2017-07-30
    相关资源
    最近更新 更多