Ekstrak nilai kolom Dataframe sebagai List di Apache Spark


87

Saya ingin mengubah kolom string dari bingkai data menjadi daftar. Yang bisa saya temukan dari DataframeAPI adalah RDD, jadi saya mencoba mengubahnya kembali menjadi RDD terlebih dahulu, lalu menerapkan toArrayfungsi ke RDD. Dalam hal ini, panjang dan SQL berfungsi dengan baik. Namun, hasil yang saya dapat dari RDD memiliki tanda kurung siku di sekitar setiap elemen seperti ini [A00001]. Saya bertanya-tanya apakah ada cara yang tepat untuk mengubah kolom menjadi daftar atau cara untuk menghapus tanda kurung siku.

Setiap saran akan dihargai. Terima kasih!


Jawaban:


117

Ini harus mengembalikan koleksi yang berisi daftar tunggal:

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()

Tanpa pemetaan, Anda hanya mendapatkan objek Row, yang berisi setiap kolom dari database.

Ingatlah bahwa ini mungkin akan memberi Anda daftar tipe Apa saja. ÏJika Anda ingin menentukan jenis hasil, Anda dapat menggunakan .asInstanceOf [YOUR_TYPE] dalam r => r(0).asInstanceOf[YOUR_TYPE]pemetaan

PS karena konversi otomatis Anda dapat melewati .rddbagian tersebut.


3
Untuk beberapa alasan aneh, perintah ini bekerja sebaliknya (Spark 2.1.0) collect().map(r => r(0))- apakah urutan ini memiliki kerugian?
Boern

1
Bisa lebih lambat - solusi Anda pertama-tama mengumpulkan semua data pada driver, dan setelah itu melakukan pemetaan pada driver (tanpa bantuan pelaksana), hanya menggunakan kekuatan pemrosesan dari driver tunggal.
TheMP

73

Dengan Spark 2.x dan Scala 2.11

Saya akan memikirkan 3 cara yang mungkin untuk mengonversi nilai kolom tertentu ke Daftar.

Potongan kode umum untuk semua pendekatan

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.getOrCreate    
import spark.implicits._ // for .toDF() method

val df = Seq(
    ("first", 2.0),
    ("test", 1.5), 
    ("choose", 8.0)
  ).toDF("id", "val")

Pendekatan 1

df.select("id").collect().map(_(0)).toList
// res9: List[Any] = List(one, two, three)

Apa yang terjadi sekarang? Kami mengumpulkan data ke Pengemudi dengan collect()dan memilih elemen nol dari setiap catatan.

Ini bukanlah cara terbaik untuk melakukannya, Mari kita tingkatkan dengan pendekatan selanjutnya.


Pendekatan 2

df.select("id").rdd.map(r => r(0)).collect.toList 
//res10: List[Any] = List(one, two, three)

Bagaimana lebih baik? Kami telah mendistribusikan beban transformasi peta di antara para pekerja daripada Pengemudi tunggal.

Aku tahu rdd.map(r => r(0))sepertinya kamu tidak elegan. Jadi, mari kita bahas itu dalam pendekatan selanjutnya.


Pendekatan 3

df.select("id").map(r => r.getString(0)).collect.toList 
//res11: List[String] = List(one, two, three)

Di sini kami tidak mengonversi DataFrame ke RDD. Lihat mapitu tidak akan menerima r => r(0)(atau _(0)) sebagai pendekatan sebelumnya karena masalah encoder di DataFrame. Jadi akhirnya gunakan r => r.getString(0)dan itu akan ditangani di versi Spark berikutnya.

Kesimpulan

Semua opsi memberikan output yang sama tetapi 2 dan 3 efektif, akhirnya yang ketiga efektif dan elegan (menurut saya).

Notebook Databricks


24

Saya tahu jawaban yang diberikan dan diminta diasumsikan untuk Scala, jadi saya hanya memberikan sedikit potongan kode Python jika pengguna PySpark penasaran. Sintaksnya mirip dengan jawaban yang diberikan, tetapi untuk memunculkan daftar dengan benar, saya sebenarnya harus merujuk nama kolom untuk kedua kalinya dalam fungsi pemetaan dan saya tidak memerlukan pernyataan pilih.

yaitu A DataFrame, berisi kolom bernama "Raw"

Untuk mendapatkan setiap nilai baris dalam "Raw" digabungkan sebagai daftar di mana setiap entri adalah nilai baris dari "Raw" saya cukup menggunakan:

MyDataFrame.rdd.map(lambda x: x.Raw).collect()

4
Ini memberikan daftar objek Row. Bagaimana jika Anda menginginkan daftar nilai?
ThatDataGuy

Ini memberikan daftar nilai.
abby sobh

Terima kasih telah membagikan ini! Ini bekerja untuk saya dengan sangat baik hanya bertanya-tanya apakah ada cara untuk mempercepat ini, ini berjalan cukup lambat
Mojgan Mazouchi

5

Di Scala dan Spark 2+, coba ini (dengan asumsi nama kolom Anda adalah "s"): df.select('s).as[String].collect


3
sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets

itu bekerja dengan sempurna


2
from pyspark.sql.functions import col

df.select(col("column_name")).collect()

di sini mengumpulkan adalah fungsi-fungsi yang pada gilirannya mengubahnya menjadi daftar. Berhati-hatilah dalam menggunakan daftar pada kumpulan data yang sangat besar. Ini akan menurunkan kinerja. Ini bagus untuk memeriksa data.


1
List<String> whatever_list = df.toJavaRDD().map(new Function<Row, String>() {
    public String call(Row row) {
        return row.getAs("column_name").toString();
    }
}).collect();

logger.info(String.format("list is %s",whatever_list)); //verification

Karena belum ada yang memberikan solusi apapun di java (Real Programming Language) Bisa terima kasih nanti


0

Solusi terbaru yang memberi Anda daftar:

dataFrame.select("YOUR_COLUMN_NAME").map(r => r.getString(0)).collect.toList

-1

Ini adalah jawaban java.

df.select("id").collectAsList();

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.