根据其他两列的最小值添加新列

时间:2020-06-07 01:30:45

标签: apache-spark apache-spark-sql

我有一个如下所示的数据框

id  id1 seq_nbr     id2 orig_id1  orig_id2  
1   740     2       217     740     217         
1   740     3       216     740     216
1   740     4       216     740     216
1   740     5       217     740     217
1   367     1       217     740     217

我需要基于orig_id1,orig_id2添加名为orig_seq_nbr的新列。预期的输出是

id  id1 seq_nbr     id2 orig_id1  orig_id2 orig_seq_nbr
1   740     3       216     740     216         3
1   740     4       216     740     216         3
1   740     5       217     740     217         2
1   367     1       217     740     217         2
1   740     2       217     740     217         2

前两行包含3,因为orig_id1,orig_id2具有740,216,并且基于id1,id2列的seq_nbr的最小值(740,216)为3。 最后三行包含2,因为orig_id1,orig_id2具有740,217,并且基于id1,id2列的seq_nbr的最小值(740,217)为2。

我试图根据orig_id1,orig_id2找到最小值,但结果如下所示

val win = Window.partitionBy("orig_id1", "orig_id2")
df1.withColumn("orig_seq_nbr",min(col("seq_nbr")).over(win)).show()
id  id1 seq_nbr     id2 orig_id1  orig_id2 orig_seq_nbr
1   740     3       216     740     216         3
1   740     4       216     740     216         3
1   740     5       217     740     217         1
1   367     1       217     740     217         1
1   740     2       217     740     217         1

对于最后三行,我应该如何更改以将orig_seq_nbr设置为2?

1 个答案:

答案 0 :(得分:0)

尝试这种方法-

1。加载测试数据

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
<LinearLayout
    android:layout_width="409dp"
    android:layout_height="729dp"
    android:layout_marginStart="1dp"
    android:layout_marginLeft="1dp"
    android:layout_marginTop="1dp"
    android:layout_marginEnd="1dp"
    android:layout_marginRight="1dp"
    android:layout_marginBottom="1dp"
    android:orientation="vertical"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <TextView
        android:id="@+id/edtName"
        android:layout_width="match_parent"
        android:layout_height="44dp"
        android:text="Name" />

    <ScrollView
        android:id="@+id/scrlText"
        android:layout_width="match_parent"
        android:fillViewport="true"
        android:isScrollContainer="true"
        android:layout_height="638dp">

        <LinearLayout
            android:id="@+id/lltext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" />
    </ScrollView>

    <LinearLayout
        android:id="@+id/hllsend"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/edtInput"
            android:layout_width="159dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:inputType="textPersonName" />

        <Button
            android:id="@+id/btnSend"
            android:layout_width="10dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Button" />
    </LinearLayout>


</LinearLayout>
</LinearLayout>

2。使用DSL

val data =
      """
        |id | id1 | seq_nbr   |  id2 |orig_id1 | orig_id2
        |1  | 740 |     2     |  217 |    740  |   217
        |1  | 740 |     3     |  216 |    740  |   216
        |1  | 740 |     4     |  216 |    740  |   216
        |1  | 740 |     5     |  217 |    740  |   217
        |1  | 367 |     1     |  217 |    740  |   217
      """.stripMargin

    val stringDS1 = data.split(System.lineSeparator())
      .map(_.split("\\|").map(_.replaceAll("""^[ \t]+|[ \t]+$""", "")).mkString(","))
      .toSeq.toDS()
    val df1 = spark.read
      .option("sep", ",")
      .option("inferSchema", "true")
      .option("header", "true")
      .option("nullValue", "null")
      .csv(stringDS1)
    df1.show(false)
    df1.printSchema()

    /**
      * +---+---+-------+---+--------+--------+
      * |id |id1|seq_nbr|id2|orig_id1|orig_id2|
      * +---+---+-------+---+--------+--------+
      * |1  |740|2      |217|740     |217     |
      * |1  |740|3      |216|740     |216     |
      * |1  |740|4      |216|740     |216     |
      * |1  |740|5      |217|740     |217     |
      * |1  |367|1      |217|740     |217     |
      * +---+---+-------+---+--------+--------+
      *
      * root
      * |-- id: integer (nullable = true)
      * |-- id1: integer (nullable = true)
      * |-- seq_nbr: integer (nullable = true)
      * |-- id2: integer (nullable = true)
      * |-- orig_id1: integer (nullable = true)
      * |-- orig_id2: integer (nullable = true)
      */

3。使用SQL表达式

 val win = Window.partitionBy("orig_id1", "orig_id2")
    df1.withColumn("orig_seq_nbr",
      min(when($"orig_id1" === $"id1" && $"orig_id2" === $"id2", $"seq_nbr").otherwise(null))
      .over(win)
    ).show()

    /**
      * +---+---+-------+---+--------+--------+------------+
      * | id|id1|seq_nbr|id2|orig_id1|orig_id2|orig_seq_nbr|
      * +---+---+-------+---+--------+--------+------------+
      * |  1|740|      3|216|     740|     216|           3|
      * |  1|740|      4|216|     740|     216|           3|
      * |  1|740|      2|217|     740|     217|           2|
      * |  1|740|      5|217|     740|     217|           2|
      * |  1|367|      1|217|     740|     217|           2|
      * +---+---+-------+---+--------+--------+------------+
      */