Фильтровать кадр данных по значению, которое НЕ присутствует в столбце другого кадра данных

Немного ударился головой об этом, и я подозреваю, что ответ очень прост. Учитывая два фрейма данных, я хочу отфильтровать первый, где значения в одном столбце отсутствуют в столбце другого фрейма данных.

Я хотел бы сделать это, не прибегая к полномасштабному Spark SQL, поэтому просто используя DataFrame.filter, или Column.contains, или ключевое слово «isin», или один из методов соединения.

val df1 = Seq(("Hampstead", "London"), 
              ("Spui", "Amsterdam"), 
              ("Chittagong", "Chennai")).toDF("location", "city")
val df2 = Seq(("London"),("Amsterdam"), ("New York")).toDF("cities")

val res = df1.filter(df2("cities").contains("city") === false)
// doesn't work, nor do the 20 other variants I have tried

У кого-нибудь есть идеи?


person Chondrops    schedule 25.10.2016    source источник
comment
попробуйте приведенный ниже код, он будет работать: - val df3 = Seq((Hampstead, London), (Spui, Amsterdam), (Chittagong, Chennai)).toDF(location, city) val df4 = Seq((London),(Amsterdam ), (Нью-Йорк)).toDF(города) df3.where(df3(город).isInCollection(df4.map(_.getString(0)).collect())).show()   -  person Ankit Tripathi    schedule 30.12.2020


Ответы (2)


Я обнаружил, что могу решить это, используя более простой метод — кажется, что антисоединение возможно в качестве параметра метода соединения, но Spark Scaladoc не описывает его:

import org.apache.spark.sql.functions._

val df1 = Seq(("Hampstead", "London"), 
              ("Spui", "Amsterdam"), 
              ("Chittagong", "Chennai")).toDF("location", "city")
val df2 = Seq(("London"),("Amsterdam"), ("New York")).toDF("cities")

df1.join(df2, df1("city") === df2("cities"), "leftanti").show

Результат:

+----------+-------+ 
|  location|   city| 
+----------+-------+ 
|Chittagong|Chennai| 
+----------+-------+  

P.S. спасибо за указатель на дубликат - должным образом помечен как таковой

person Chondrops    schedule 25.10.2016

Если вы пытаетесь отфильтровать DataFrame с помощью другого, вам следует использовать join (или любой из его вариантов). Если вам нужно отфильтровать его с помощью List или любой другой структуры данных, которая подходит для вашего мастера и рабочих, вы можете передать ее, а затем сослаться на нее внутри метода filter или where.

Например, я бы сделал что-то вроде:

import org.apache.spark.sql.functions._

val df1 = Seq(("Hampstead", "London"), 
              ("Spui", "Amsterdam"), 
              ("Chittagong", "Chennai")).toDF("location", "city")
val df2 = Seq(("London"),("Amsterdam"), ("New York")).toDF("cities")

df2.join(df1, joinExprs=df1("city") === df2("cities"), joinType="full_outer")
   .select("city", "cities")
   .where(isnull($"cities"))
   .drop("cities").show()
person Alberto Bonsanto    schedule 25.10.2016
comment
Хорошо, но какое соединение позволит достичь желаемого результата? Я считаю, что мне следует обратить внимание на антисоединение, но, согласно Scaladoc, это не вариант. Кроме того, я согласен с тем, что я могу использовать фильтр в списке (... что-то вроде df.filter(($col isin ‹list›) === false), но тогда как я могу превратить столбец, на который я хочу ссылаться, в Список? - person Chondrops; 25.10.2016