У меня есть фрейм данных со многими столбцами, который я создал из файла CSV, определяющего схему. Единственный интересующий меня столбец - это столбец «Точка», в котором я определил точку Магеллана (long, lat). Что мне нужно сделать сейчас, это создать RDD [Point] из этого кадра данных.

Ниже приведен код, который я пробовал, но он не работает, поскольку rdd является RDD [Row] вместо RDD [Point].

val schema = StructType(Array(
         StructField("vendorId", StringType, false),
         StructField("lpep_pickup_datetime", StringType, false),
         StructField("Lpep_dropoff_datetime", StringType, false),
         StructField("Store_and_fwd_flag",StringType, false),
         StructField("RateCodeID", IntegerType, false),
         StructField("Pickup_longitude", DoubleType, false),
         StructField("Pickup_latitude", DoubleType, false),
         StructField("Dropoff_longitude", DoubleType, false),
         StructField("Dropoff_latitude", DoubleType, false),
         StructField("Passenger_count", IntegerType, false),
         StructField("Trip_distance", DoubleType, false),
         StructField("Fare_amount", StringType, false),
         StructField("Extra", StringType, false),
         StructField("MTA_tax", StringType, false),
         StructField("Tip_amount", StringType, false),
         StructField("Tolls_amount", StringType, false),
         StructField("Ehail_fee", StringType, false),
         StructField("improvement_surcharge", StringType, false),
         StructField("Total_amount", DoubleType, false),
         StructField("Payment_type", IntegerType, false),
         StructField("Trip_type", IntegerType, false)))

    import spark.implicits._

    val points = spark.read.option("mode", "DROPMALFORMED")
     .schema(schema)
     .csv("/home/riccardo/Scrivania/Progetto/Materiale/NYC-taxi/")
     .withColumn("point", point($"Pickup_longitude",$"Pickup_latitude"))
     .limit(2000)

    val rdd = points.select("point").rdd

Как получить RDD [Point] вместо RDD [Row] из кадра данных? Если это невозможно, какое решение вы бы предложили? Мне нужен RDD [Point] для работы с предоставленной библиотекой, которая принимает RDD [Point] в качестве входных данных.

0
Riccardo Fiorini 19 Апр 2019 в 14:03

2 ответа

Лучший ответ

Если я правильно понимаю, вы хотите, чтобы результат был пользовательского типа класса Point вместо Row

Вот что я пробовал:

Мой пример входных данных:

latitude,longitude
44.968046,-94.420307
44.968046,-94.420307
44.33328,-89.132008
33.755787,-116.359998
33.844843,-116.54911
44.92057,-93.44786
44.240309,-91.493619
44.968041,-94.419696
44.333304,-89.132027

Я создал свой пользовательский класс с toString()

case class Pair(latitude: Double, longitude: Double) {
  override def toString: String = s"Pair($latitude, $longitude)"
}

Теперь я читаю входной файл, используя spark как DataFrame, и конвертирую его в RDD

val df = sparkSession.read.option("inferSchema", "true")
  .option("header", "true")
  .csv("/home/prasadkhode/sample_input.csv")

df.printSchema()
df.show()

val rdd = df.rdd.map(row => {
  Pair(row.getAs[Double]("latitude"), row.getAs[Double]("longitude"))
})

println(s"df count : ${df.count}")
println(s"rdd count : ${rdd.count}")

rdd.take(20).foreach(println)

И, наконец, результат выглядит следующим образом:

root
 |-- latitude: double (nullable = true)
 |-- longitude: double (nullable = true)

+---------+-----------+
| latitude|  longitude|
+---------+-----------+
|44.968046| -94.420307|
|44.968046| -94.420307|
| 44.33328| -89.132008|
|33.755787|-116.359998|
|33.844843| -116.54911|
| 44.92057|  -93.44786|
|44.240309| -91.493619|
|44.968041| -94.419696|
|44.333304| -89.132027|
+---------+-----------+

df count : 9
rdd count : 9

Pair(44.968046, -94.420307)
Pair(44.968046, -94.420307)
Pair(44.33328, -89.132008)
Pair(33.755787, -116.359998)
Pair(33.844843, -116.54911)
Pair(44.92057, -93.44786)
Pair(44.240309, -91.493619)
Pair(44.968041, -94.419696)
Pair(44.333304, -89.132027)

Надеюсь, это поможет вам ... :-)

1
Prasad Khode 19 Апр 2019 в 12:01

Методы "as" и "rdd" могут помочь:

case class Point(latitude: Double, longitude: Double)

val df = Seq((1.0, 2.0)).toDF("Pickup_longitude", "Pickup_latitude")

val rdd = df
  .select(
    $"Pickup_longitude".alias("latitude"),
    $"Pickup_latitude".alias("longitude"))
  .as[Point].rdd

rdd.foreach(println)

Выход:

Point(1.0,2.0)
0
pasha701 19 Апр 2019 в 19:13