Misalkan saya melakukan sesuatu seperti:
val df = sqlContext.load("com.databricks.spark.csv", Map("path" -> "cars.csv", "header" -> "true"))
df.printSchema()
root
|-- year: string (nullable = true)
|-- make: string (nullable = true)
|-- model: string (nullable = true)
|-- comment: string (nullable = true)
|-- blank: string (nullable = true)
df.show()
year make model comment blank
2012 Tesla S No comment
1997 Ford E350 Go get one now th...
Tetapi saya benar-benar menginginkan year
as Int
(dan mungkin mengubah beberapa kolom lainnya).
Yang terbaik yang bisa saya pikirkan adalah
df.withColumn("year2", 'year.cast("Int")).select('year2 as 'year, 'make, 'model, 'comment, 'blank)
org.apache.spark.sql.DataFrame = [year: int, make: string, model: string, comment: string, blank: string]
yang agak berbelit-belit.
Saya berasal dari R, dan saya sudah terbiasa menulis, misalnya
df2 <- df %>%
mutate(year = year %>% as.integer,
make = make %>% toupper)
Saya mungkin melewatkan sesuatu, karena harus ada cara yang lebih baik untuk melakukan ini di Spark / Scala ...
scala
apache-spark
apache-spark-sql
kevinykuo
sumber
sumber
Jawaban:
Sunting: Versi terbaru
Karena percikan 2.x dapat Anda gunakan
.withColumn
. Periksa dokumen di sini:https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.sql.Dataset@withColumn(colName:String,col:org.apache.spark.sql.Column) : org.apache.spark.sql.DataFrame
Jawaban tertua
Sejak Spark versi 1.4 Anda dapat menerapkan metode cor dengan DataType pada kolom:
Jika Anda menggunakan ekspresi sql, Anda juga dapat melakukan:
Untuk info lebih lanjut, periksa dokumen: http://spark.apache.org/docs/1.6.0/api/scala/#org.apache.spark.sql.DataFrame
sumber
df.withColumn("ctr", temp("ctr").cast(DecimalType(decimalPrecision, decimalScale)))
Spark 2.x
,df.withColumn(..)
dapat menambah atau mengganti kolom tergantung padacolName
argumen[EDIT: Maret 2016: terima kasih untuk suaranya! Meskipun sungguh, ini bukan jawaban terbaik, saya pikir solusi berdasarkan
withColumn
,withColumnRenamed
dancast
diajukan oleh msemelman, Martin Senne dan yang lainnya lebih sederhana dan lebih bersih].Saya pikir pendekatan Anda ok, ingat bahwa Spark
DataFrame
adalah RDD (tidak berubah) dari Baris, jadi kami tidak pernah benar-benar mengganti kolom, hanya membuat baruDataFrame
setiap kali dengan skema baru.Dengan asumsi Anda memiliki df asli dengan skema berikut:
Dan beberapa UDF didefinisikan pada satu atau beberapa kolom:
Mengubah jenis kolom atau bahkan membangun DataFrame baru dari yang lain dapat ditulis seperti ini:
yang menghasilkan:
Ini cukup dekat dengan solusi Anda sendiri. Sederhananya, menjaga jenis perubahan dan transformasi lainnya sebagai terpisah
udf val
membuat kode lebih mudah dibaca dan digunakan kembali.sumber
NULL
entri tunggal atau cacat akan merusak seluruh pekerjaan. Tidak efisien karena UDF tidak transparan ke Catalyst. Menggunakan UDF untuk operasi yang kompleks tidak masalah, tetapi tidak ada alasan untuk menggunakannya untuk tipe casting dasar. Ini sebabnya kami memilikicast
metode (lihat jawaban oleh Martin Senne ). Membuat hal-hal yang transparan untuk Catalyst membutuhkan lebih banyak pekerjaan tetapi keselamatan dasar hanyalah masalah menempatkanTry
danOption
bekerja.withColumn()
bagian Anda menjadi bagian umum yang beriterasi melalui semua kolom?Karena
cast
operasi ini tersedia untuk SparkColumn
(dan karena saya pribadi tidak mendukungudf
seperti yang diusulkan oleh @Svend
pada titik ini), bagaimana dengan:untuk dilemparkan ke jenis yang diminta? Sebagai efek samping yang rapi, nilai-nilai yang tidak dapat dicastai / "dikonversi" dalam arti itu, akan menjadi
null
.Jika Anda membutuhkan ini sebagai metode pembantu , gunakan:
yang digunakan seperti:
sumber
Pertama , jika Anda ingin mengetikkan tipe, maka ini:
Dengan nama kolom yang sama, kolom akan diganti dengan yang baru. Anda tidak perlu melakukan langkah-langkah menambah dan menghapus.
Kedua , tentang Scala vs R .
Ini adalah kode yang paling mirip dengan RI dapat muncul dengan:
Padahal panjang kode sedikit lebih panjang dari R. Itu tidak ada hubungannya dengan verbositas bahasa. Dalam R
mutate
adalah fungsi khusus untuk kerangka data R, sementara di Scala Anda dapat dengan mudah menambahkannya berkat kekuatan ekspresifnya.Singkatnya, ini menghindari solusi spesifik, karena desain bahasa cukup baik bagi Anda untuk dengan cepat dan mudah membangun bahasa domain Anda sendiri.
catatan:
df.columns
secara mengejutkanArray[String]
bukanArray[Column]
, mungkin mereka ingin itu terlihat seperti kerangka data Python panda.sumber
import org.apache.spark.sql.types._
dan kemudian bukansql.types.IntegerType
hanyaIntegerType
.Anda dapat menggunakannya
selectExpr
untuk membuatnya sedikit lebih bersih:sumber
Kode Java untuk memodifikasi datatype DataFrame dari String ke Integer
Ini hanya akan membuang yang ada (String datatype) ke Integer.
sumber
DataTypes
di dalamsql.types
! ituDataType
. Selain itu, seseorang dapat dengan mudah mengimporIntegerType
dan melemparkan.DataTypes.IntegerType
dulunya dalam mode DeveloperAPI dan stabil di v.2.1.0Untuk mengkonversi tahun dari string ke int, Anda dapat menambahkan opsi berikut ke pembaca csv: "inferSchema" -> "true", lihat dokumentasi DataBricks
sumber
Jadi ini hanya benar-benar berfungsi jika Anda mengalami masalah menabung ke driver jdbc seperti sqlserver, tetapi ini sangat membantu untuk kesalahan yang akan Anda hadapi dengan sintaks dan tipe.
sumber
Hasilkan dataset sederhana yang berisi lima nilai dan konversi
int
untukstring
mengetik:sumber
Saya pikir ini lebih mudah dibaca untuk saya.
Ini akan mengonversi kolom tahun Anda menjadi
IntegerType
dengan membuat kolom sementara apa saja dan menjatuhkan kolom-kolom itu. Jika Anda ingin mengonversi ke tipe data lain, Anda dapat memeriksa jenis di dalamorg.apache.spark.sql.types
paket.sumber
jawaban yang menyarankan untuk menggunakan cast, FYI, metode cast dalam spark 1.4.1 rusak.
misalnya, kerangka data dengan kolom string yang memiliki nilai "8182175552014127960" ketika dicor ke bigint memiliki nilai "8182175552014128100"
Kami harus menghadapi banyak masalah sebelum menemukan bug ini karena kami memiliki kolom bigint dalam produksi.
sumber
sumber
Menggunakan Spark Sql 2.4.0 Anda dapat melakukannya:
sumber
Anda dapat menggunakan kode di bawah ini.
Yang akan mengkonversi kolom tahun ke
IntegerType
kolom.sumber
Metode ini akan menjatuhkan kolom lama dan membuat kolom baru dengan nilai dan tipe data yang sama. Tipe data asli saya saat DataFrame dibuat adalah: -
Setelah ini saya menjalankan kode berikut untuk mengubah tipe data: -
Setelah ini hasil saya keluar menjadi: -
sumber
Seseorang dapat mengubah tipe data kolom dengan menggunakan cast in spark sql. nama tabel adalah tabel dan memiliki dua kolom, hanya kolom1 dan kolom2 dan tipe data1 kolom harus diubah. ex-spark.sql ("pilih cast (column1 as Double) column1NewName, column2 from table") Di tempat double tulis tipe data Anda.
sumber
Jika Anda harus mengganti nama lusinan kolom dengan namanya, contoh berikut menggunakan pendekatan @dnlbrky dan menerapkannya ke beberapa kolom sekaligus:
Kolom yang belum diputar disimpan tidak berubah. Semua kolom tetap dalam urutan aslinya.
sumber
Begitu banyak jawaban dan tidak banyak penjelasan menyeluruh
Sintaks berikut berfungsi Menggunakan Notebook Databricks dengan Spark 2.4
Perhatikan bahwa Anda harus menentukan format entri yang Anda miliki (dalam kasus saya "MM-dd-yyyy") dan impor wajib karena to_date adalah fungsi sql percikan
Juga Mencoba sintaks ini tetapi mendapat nol alih-alih pemeran yang tepat:
(Catatan saya harus menggunakan tanda kurung dan tanda kutip agar benar secara sintaksis)
PS: Saya harus mengakui ini seperti hutan sintaksis, ada banyak cara masuk yang memungkinkan, dan referensi API resmi tidak memiliki contoh yang tepat.
sumber
Solusi lain adalah sebagai berikut:
1) Simpan "inferSchema" sebagai False
2) Saat menjalankan fungsi 'Peta' di baris, Anda dapat membaca 'asString' (row.getString ...)
sumber
Mengapa tidak lakukan seperti yang dijelaskan di bawah http://spark.apache.org/docs/latest/api/python/pyspark.sql.html#pyspark.sql.Column.cast
sumber
sumber
Cara lain:
sumber
Dalam kasus jika Anda ingin mengubah beberapa kolom dari jenis tertentu ke yang lain tanpa menentukan nama kolom individual
sumber