Вы можете достичь желаемого с помощью оконных функций:
import org.apache.spark.sql.expressions.Window._
ds.withColumn("aux", count("*")
.over(Window.partitionBy($"userId", $"VTS")))
.where($"aux"===1)
.drop($"aux")
partitionBy будет подсчитывать, сколько элементов по разделам, в соответствии со столбцами, которые вы отправляете в качестве параметров (userId и VTS в вашем примере).
Затем с помощью предложения where
мы будем хранить только строки из разделов, в которых количество равно 1, то есть уникальные строки.
Результат предложения partitionBY
ds.withColumn("aux", count("*").over(Window.partitionBy($"userId", $"VTS"))).show
+-------+----+------------+------------+---+
| userId| VTS| moreColumn1| moreColumn2|aux|
+-------+----+------------+------------+---+
| 10| 150| 2| 3| 2|
| 10| 150| 0| 1| 2|
| 11| 160| 1| 6| 1|
+-------+----+------------+------------+---+
Окончательный результат
+-------+----+------------+------------+
| userId| VTS| moreColumn1| moreColumn2|
+-------+----+------------+------------+
| 11| 160| 1| 6|
+-------+----+------------+------------+