【发布时间】:2018-03-07 16:41:16
【问题描述】:
我想对我的 DataFrame df 执行转换,这样我每个键在最终 DataFrame 中只有一次且只有一次。
出于机器学习的目的,我不想在我的数据集中存在偏见。这绝不应该发生,但我从数据源获得的数据包含这种“怪异”。因此,如果我有具有相同键的行,我希望能够选择两者的组合(如平均值)或字符串连接(例如标签)或随机值集。
假设我的 DataFrame df 看起来像这样:
+---+----+-----------+---------+
|ID1| ID2| VAL1| VAL2|
+---+----+-----------+---------+
| A| U| PIERRE| 1|
| A| U| THOMAS| 2|
| A| U| MICHAEL| 3|
| A| V| TOM| 2|
| A| V| JACK| 3|
| A| W| MICHEL| 2|
| A| W| JULIEN| 3|
+---+----+-----------+---------+
我希望我的最终 DataFrame out 仅随机保留每个键的一组值。它可能是另一种类型的聚合(例如将所有值串联为字符串),但我只是不想从中构建 Integer 值,而是构建新条目。
例如。最终输出可能是(仅保留每个键的第一行):
+---+----+-----------+---------+
|ID1| ID2| VAL1| VAL2|
+---+----+-----------+---------+
| A| U| PIERRE| 1|
| A| V| TOM| 2|
| A| W| MICHEL| 2|
+---+----+-----------+---------+
另一个最终输出可能是(每个键保持随机行):
+---+----+-----------+---------+
|ID1| ID2| VAL1| VAL2|
+---+----+-----------+---------+
| A| U| MICHAEL| 3|
| A| V| JACK| 3|
| A| W| MICHEL| 2|
+---+----+-----------+---------+
或者,建立一组新的价值观:
+---+----+--------------------------+----------+
|ID1| ID2| VAL1| VAL2|
+---+----+--------------------------+----------+
| A| U| (PIERRE, THOMAS, MICHAEL)| (1, 2, 3)|
| A| V| (TOM, JACK)| (2, 3)|
| A| W| (MICHEL, JULIEN)| (2, 3)|
+---+----+--------------------------+----------+
答案应该是使用 Spark 和 Scala。我还想强调,实际的架构比这要复杂得多,我想找到一个通用的解决方案。此外,我不想仅从一列中获取唯一值,但过滤掉具有相同键的行。谢谢!
编辑这是我尝试做的(但Row.get(colname) 抛出NoSuchElementException: key not found...):
def myDropDuplicatesRandom(df: DataFrame, colnames: Seq[String]): DataFrame = {
val fields_map: Map[String, (Int, DataType)] =
df.schema.fieldNames.map(fname => {
val findex = df.schema.fieldIndex(fname)
val ftype = df.schema.fields(findex).dataType
(fname, (findex, ftype))
}).toMap[String, (Int, DataType)]
df.sparkSession.createDataFrame(
df.rdd
.map[(String, Row)](r => (colnames.map(colname => r.get(fields_map(colname)._1).toString.replace("`", "")).reduceLeft((x, y) => "" + x + y), r))
.groupByKey()
.map{case (x: String, y: Iterable[Row]) => Utils.randomElement(y)}
, df.schema)
}
【问题讨论】:
-
@David 我不是在一列上寻找不同的值,而是在寻找一种方法来过滤掉具有相同键的值。
-
您似乎想根据 ID2(可能还有 ID1)删除重复项。不确定我是否理解您的问题与此有何不同。 “钥匙”是什么意思?
-
因此,您可以根据
ID1和ID2使用dropDuplicates -
啊,我的错。很难找到一个好的 scala spark 答案,我是 pyspark 用户。你会想要使用
dropDuplicates。表单将类似于val out = df.dropDuplicates(Seq("ID1", "ID2"))
标签: scala apache-spark spark-dataframe rdd