首页 > 解决方案 > 根据其他数据集中的列表查找缺失值的列名

问题描述

nominals是我的参考数据集,其中包含每天在某台机器上测量的所有点。它具有以下简化结构

nominals
+------------+----+----+-----+----+
| point_name |   x|   y|    z|side|
+------------+----+----+-----+----+
|str1        |.   |.   |.    | .  |
|str2        |.   |.   |.    | .  |
|str3        |.   |.   |.    | .  |
+------------+----+----+-----+----+

x,y,z是标称点坐标。是测量点的point_name唯一标识符,包含side. 因此,每一面都有一个需要测量的点的列表,例如在伪代码point_name[point_name.side=="L"].unique()中。

存储实际测量值的数据集具有类似的结构,但有一个额外的列id来标识正在测量的机器。每个id都有被测量的左侧和右侧。

actuals
+------------+----+----+-----+----+----+
| point_name |   x|   y|    z|side| id |
+------------+----+----+-----+----+----+
|str4        |.   |.   |.    | .  |.   |
|str5        |.   |.   |.    | .  |.   |
|str6        |.   |.   |.    | .  |.   |
+------------+----+----+-----+----+----+

现在,我想创建一个新数据集,其中包含一个附加列,其中列出了每id-side对夫妇的测量数据集中缺失的所有点。换句话说,对于每一种id-side组合,我都需要检查point_name实际测量值中存在的列表与名义测量值之间的差异,并找出两者之间的差异。预期结果将是

+-----------------------+-----------+
| id |   missing_L      | missing_R |
+-----------------------+-----------+
|9433| point_1, point_12|  point_14 |  
|9512| null             |  point_15 |
+-----------------------+-----------+

在当前的解决方案中,我正在旋转point_name并检查具有null值的列。

nominals_left = (
        nominals
        .filter(nominals.side == "L")
        .select("point_name")
)
nominals_left_list = nominals_left.rdd.flatMap(lambda x: x).collect()

actuals_left = (
        actuals
        .filter(actuals.side == "L")
        .groupBy("id")
        .pivot("point_name", values=nominals_left_list)
        .sum("x")
    )
actuals_left_final = (
        actuals_left
        .withColumn("missing_L", F.array(*[F.when(F.isnull(c), F.lit(c)) for c in actuals_left.columns]))
        .withColumn("missing_L", F.expr("array_join(missing_L, ', ')"))
        .select("id", "missing_L")
    )

有没有更简单或更有效的方法来做到这一点?此外,似乎我必须明确地对每个进行相同的检查,side以避免由于属于另一侧的点而产生误报空值。将id和完全分组会很好side

标签: pythonapache-sparkpysparkapache-spark-sql

解决方案


我想我在研究更多之后找到了一种方法。我只是从标称表中创建所有所需点的列表,将其与测量表连接起来side,然后在这两列数组之间进行区分。似乎工作正常。nominals这是给定表格和表格的示例actualsid首先创建一个所有标称点的列表side

nominal_list = (
    nominals
    .groupby("side")
    .agg(F.collect_list(F.col("point_name")))
    .withColumnRenamed("collect_list(point_name)", "nominal_points")
)

然后加入使用附加列创建的类似数据集id(请注意调用时数组的顺序F.array_except)。

missing = (
    actuals
    .groupby(["id", "side"])
    .agg(F.collect_list(F.col("point_name")))
    .withColumnRenamed("collect_list(point_name)", "measured_points")
    .join(nominal_list, "side")
    .withColumn('missing', F.array_except('nominal_points', 'measured_points'))
)

请注意,这与我在开始时询问的内容略有不同,因为我将一侧作为附加列,而不是隐藏在列名中,即missing_Lmissing_R


推荐阅读