加入 Dataframe 的相同列后,Drop 功能无法正常工作

Posted

技术标签:

【中文标题】加入 Dataframe 的相同列后,Drop 功能无法正常工作【英文标题】:Drop function doesn't work properly after joining same columns of Dataframe 【发布时间】:2019-10-07 18:53:09 【问题描述】:

我在加入两个数据框 A、B 时遇到了同样的问题。

例如:

c = df_a.join(df_b, [df_a.col1 == df_b.col1], how="left").drop(df_b.col1)

当我尝试像上面那样删除重复列时,此查询不会删除 df_b 的 col1。相反,当我尝试删除 df_a 的 col1 时,它能够删除 df_a 的 col1。

谁能说说这个。

注意:我在我的项目中尝试了相同的方法,该项目有 200 多个列并显示相同的问题。有时,如果我们的列数很少,这个 drop 函数可以正常工作,但如果我们有更多的列,则不能。

Drop function not working after left outer join in pyspark

【问题讨论】:

你能在声明后显示c.printSchema()的输出吗? 就说.drop("col1") 为什么不按照你链接的问题中的答案做df_a.join(df_b, ['col1'], how="left") @Shaido 我想要其他解决方案而不是这个。 【参考方案1】:

合并后删除重复列的功能。

def dropDupeDfCols(df):
newcols = []
dupcols = []

for i in range(len(df.columns)):
    if df.columns[i] not in newcols:
        newcols.append(df.columns[i])
    else:
        dupcols.append(i)

df = df.toDF(*[str(i) for i in range(len(df.columns))])
for dupcol in dupcols:
    df = df.drop(str(dupcol))

return df.toDF(*newcols) 

【讨论】:

@NicoHaase 它是一个比较两列列表的简单函数,如果存在重复,则只需将其删除。 请通过编辑将所有解释添加到您的答案中【参考方案2】:

我最近遇到了一些类似的问题。让我在下面用你的案例来展示它们。

我正在创建两个具有相同数据的数据框

scala> val df_a = Seq((1, 2, "as"), (2,3,"ds"), (3,4,"ew"), (4, 1, "re"), (3,1,"ht")).toDF("a", "b", "c")
df_a: org.apache.spark.sql.DataFrame = [a: int, b: int ... 1 more field]

scala> val df_b = Seq((1, 2, "as"), (2,3,"ds"), (3,4,"ew"), (4, 1, "re"), (3,1,"ht")).toDF("a", "b", "c")
df_b: org.apache.spark.sql.DataFrame = [a: int, b: int ... 1 more field]

加入他们

scala> val df = df_a.join(df_b, df_a("b") === df_b("a"), "leftouter")
df: org.apache.spark.sql.DataFrame = [a: int, b: int ... 4 more fields]

scala> df.show
+---+---+---+---+---+---+
|  a|  b|  c|  a|  b|  c|
+---+---+---+---+---+---+
|  1|  2| as|  2|  3| ds|
|  2|  3| ds|  3|  1| ht|
|  2|  3| ds|  3|  4| ew|
|  3|  4| ew|  4|  1| re|
|  4|  1| re|  1|  2| as|
|  3|  1| ht|  1|  2| as|
+---+---+---+---+---+---+

让我们删除上述数据框中不存在的列

+---+---+---+---+---+---+
|  a|  b|  c|  a|  b|  c|
+---+---+---+---+---+---+
|  1|  2| as|  2|  3| ds|
|  2|  3| ds|  3|  1| ht|
|  2|  3| ds|  3|  4| ew|
|  3|  4| ew|  4|  1| re|
|  4|  1| re|  1|  2| as|
|  3|  1| ht|  1|  2| as|
+---+---+---+---+---+---+

理想情况下,我们希望 spark 会抛出错误,但它会成功执行。

现在,如果您从上述数据框中删除一列

scala> df.drop("a").show
+---+---+---+---+
|  b|  c|  b|  c|
+---+---+---+---+
|  2| as|  3| ds|
|  3| ds|  1| ht|
|  3| ds|  4| ew|
|  4| ew|  1| re|
|  1| re|  2| as|
|  1| ht|  2| as|
+---+---+---+---+

它会删除输入数据框中具有提供的列名的所有列。

如果你想删除特定的列,应该如下完成:

scala> df.drop(df_a("a")).show()
+---+---+---+---+---+
|  b|  c|  a|  b|  c|
+---+---+---+---+---+
|  2| as|  2|  3| ds|
|  3| ds|  3|  1| ht|
|  3| ds|  3|  4| ew|
|  4| ew|  4|  1| re|
|  1| re|  1|  2| as|
|  1| ht|  1|  2| as|
+---+---+---+---+---+

我认为 spark 不接受您提供的输入(见下文):


scala> df.drop(df_a.a).show()
<console>:30: error: value a is not a member of org.apache.spark.sql.DataFrame
       df.drop(df_a.a).show()
                    ^

scala> df.drop(df_a."a").show()
<console>:1: error: identifier expected but string literal found.
df.drop(df_a."a").show()
             ^

如果您提供要删除的输入,如下所示,它会执行但不会产生任何影响

scala> df.drop("df_a.a").show
+---+---+---+---+---+---+
|  a|  b|  c|  a|  b|  c|
+---+---+---+---+---+---+
|  1|  2| as|  2|  3| ds|
|  2|  3| ds|  3|  1| ht|
|  2|  3| ds|  3|  4| ew|
|  3|  4| ew|  4|  1| re|
|  4|  1| re|  1|  2| as|
|  3|  1| ht|  1|  2| as|
+---+---+---+---+---+---+

原因是,spark 将“df_a.a”解释为嵌套列。由于该列在理想情况下不存在,它应该引发错误,但如上所述,它只是执行。

希望这会有所帮助..!!!

【讨论】:

但是当我尝试在 Pyspark 中执行 drop(df_b.col1) 之类的操作时,它成功执行而没有任何影响。但我不确定 Spark。 您能否确认此答案解决了您的问题?? 但正如我所说,我上面的查询在列较少的情况下可以正常工作,因为我有更多列 Spark 不起作用。 哦.. 我已经为 Scala 提供了代码,在 PySpark 中,您使用的代码有效,但正如我在回答中所说,如果您不指定,它将删除所有列跨度> 是的,它会删除所有列,并且对于更少的列也有效。但是对于更多数量的列,这无法删除右侧重复列的列。

以上是关于加入 Dataframe 的相同列后,Drop 功能无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

Python:在相同索引上加入具有相同列前缀的两个 DataFrame

pandas使用drop函数删除dataframe中指定索引位置的数据行(drop row in dataframe with integer index)

pandas.Dataframe之drop函数解析

循环遍历数据框列后如何附加列表?

KeyError:重命名数据框列后为 1.0

等效于 pandas.DataFrame.set_index / drop_duplicates 与 dropDuplicates 的 Spark DataFrame