Saya cukup baru dalam scala dan berasal dari latar belakang sql dan panda, objek dataset di scala memberi saya sedikit masalah.

Saya memiliki kumpulan data yang terlihat seperti berikut ...

|car_num|      colour|
+-----------+---------+
|      145| c|
|      132| p|
|      104| u|
|      110| c|
|      110| f|
|      113| c|
|      115| c|
|       11| i|
|      117| s|
|      118| a|


Saya telah memuatnya sebagai kumpulan data menggunakan kelas kasus yang terlihat seperti berikut:

case class carDS(carNum: String, Colour: String)

Setiap car_num unik untuk sebuah mobil, banyak mobil memiliki banyak entri. Kolom warna mengacu pada warna mobil yang dicat.

Saya ingin tahu cara menambahkan kolom yang memberikan jumlah total pekerjaan cat yang dimiliki mobil tanpa menjadi hijau (g) ​​misalnya.

Sejauh ini saya sudah mencoba ini.

carDS
  .map(x => (x.carNum, x.Colour))
  .groupBy("_1")
  .count()
  .orderBy($"count".desc).show()

Tapi saya percaya itu hanya memberi saya kolom hitungan berapa kali mobil itu dicat. Bukan jumlah berurutan terpanjang kali mobil dicat tanpa menjadi hijau.

Saya pikir saya mungkin perlu menggunakan fungsi dalam kueri saya seperti berikut

def colourrun(sq: String): Int = {
  println(sq)
  sq.mkString(" ")
    .split("g")
    .filter(_.nonEmpty)
    .map(_.trim)
    .map(s => s.split(" ").length)
    .max
}

Tapi saya tidak yakin di mana itu harus pergi.

Akhirnya jika mobil 102 telah dicat r, b, g, b, o, y, r, g saya ingin kolom hitung memberikan 4 sebagai jawabannya.

Bagaimana saya melakukan ini? Terima kasih

0
Xaleate 11 Mei 2021, 01:47

1 menjawab

Jawaban Terbaik

Berikut adalah satu pendekatan yang melibatkan pengelompokan pekerjaan cat untuk mobil tertentu ke dalam kelompok bernomor monoton yang dipisahkan oleh pekerjaan cat warna "g", diikuti oleh beberapa groupBy/aggs untuk jumlah maksimum pekerjaan cat antara menjadi pekerjaan cat warna "g".

(Perhatikan bahwa kolom timestamp sedang ditambahkan untuk memastikan urutan deterministik baris dalam kumpulan data.)

val ds = Seq(
  ("102", "r", 1), ("102", "b", 2), ("102", "g", 3), ("102", "b", 4), ("102", "o", 5), ("102", "y", 6), ("102", "r", 7), ("102", "g", 8),
  ("145", "c", 1), ("145", "g", 2), ("145", "b", 3), ("145", "r", 4), ("145", "g", 5), ("145", "c", 6), ("145", "g", 7)
).toDF("car_num", "colour", "timestamp").as[(String, String, Long)]

import org.apache.spark.sql.expressions.Window
val win = Window.partitionBy("car_num").orderBy("timestamp")

ds.
  withColumn("group", sum(when($"colour" === "g", 1).otherwise(0)).over(win)).  // (*)
  groupBy("car_num", "group").agg(
    when($"group" === 0, count("group")).otherwise(count("group") - 1).as("count")
  ).                                                                            // (**)
  groupBy("car_num").agg(max("count").as("max_between_g")).
  show
// +-------+-------------+
// |car_num|max_between_g|
// +-------+-------------+
// |    102|            4|
// |    145|            2|
// +-------+-------------+

Jika Anda harus menempuh jalur untuk beralih ke transformasi Dataset berbasis non-SQL, pertimbangkan untuk menggunakan groupByKey diikuti dengan mapGroups seperti di bawah ini:

ds.
  map(c => (c.car_num, c.colour)).
  groupByKey(_._1).mapGroups{ case (k, iter) =>
    val maxTuple = iter.map(_._2).foldLeft((0, 0)){ case ((cnt, mx), c) =>
      if (c == "g") (0, math.max(cnt, mx)) else (cnt + 1, mx)
    }
    (k, maxTuple._2)
  }.
  show
  // +---+---+
  // | _1| _2|
  // +---+---+
  // |102|  4|
  // |145|  2|
  // +---+---+

Kumpulan data perantara (untuk referensi):

(*)
// +-------+------+---------+-----+
// |car_num|colour|timestamp|group|
// +-------+------+---------+-----+
// |    102|     r|        1|    0|
// |    102|     b|        2|    0|
// |    102|     g|        3|    1|
// |    102|     b|        4|    1|
// |    102|     o|        5|    1|
// |    102|     y|        6|    1|
// |    102|     r|        7|    1|
// |    102|     g|        8|    2|
// |    145|     c|        1|    0|
// |    145|     g|        2|    1|
// |    145|     b|        3|    1|
// |    145|     r|        4|    1|
// |    145|     g|        5|    2|
// |    145|     c|        6|    2|
// |    145|     g|        7|    3|
// +-------+------+---------+-----+

(**)
// +-------+----+-----+
// |car_num|sess|count|
// +-------+----+-----+
// |    102|   0|    2|
// |    102|   1|    4|
// |    102|   2|    0|
// |    145|   0|    1|
// |    145|   1|    2|
// |    145|   2|    1|
// |    145|   3|    0|
// +-------+----+-----+
2
Leo C 11 Mei 2021, 18:42