加入 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.set_index / drop_duplicates 与 dropDuplicates 的 Spark DataFrame