ฉันจะเปลี่ยนประเภทคอลัมน์ใน DataFrame ของ Spark SQL ได้อย่างไร


152

สมมติว่าฉันกำลังทำสิ่งที่ชอบ:

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...

แต่ฉันต้องการyearเป็นInt(และอาจแปลงคอลัมน์อื่น ๆ )

สิ่งที่ดีที่สุดที่ฉันสามารถทำได้คือ

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]

ซึ่งค่อนข้างซับซ้อน

ฉันมาจาก R และฉันคุ้นเคยกับความสามารถในการเขียนเช่น

df2 <- df %>%
   mutate(year = year %>% as.integer,
          make = make %>% toupper)

ฉันน่าจะพลาดบางสิ่งบางอย่างเนื่องจากมีวิธีที่ดีกว่าในการทำเช่นนี้ใน Spark / Scala ...


ฉันชอบวิธีนี้ spark.sql ("เลือก STRING (NULLIF (คอลัมน์, '')) เป็น column_string")
Eric

คำตอบ:


141

แก้ไข: รุ่นใหม่ล่าสุด

ตั้งแต่จุดประกาย 2.x .withColumnคุณสามารถใช้ ตรวจสอบเอกสารที่นี่:

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

คำตอบที่เก่าที่สุด

ตั้งแต่ Spark รุ่น 1.4 คุณสามารถใช้วิธีการส่งกับ DataType ในคอลัมน์:

import org.apache.spark.sql.types.IntegerType
val df2 = df.withColumn("yearTmp", df.year.cast(IntegerType))
    .drop("year")
    .withColumnRenamed("yearTmp", "year")

หากคุณใช้นิพจน์ sql คุณสามารถทำได้ดังนี้

val df2 = df.selectExpr("cast(year as int) year", 
                        "make", 
                        "model", 
                        "comment", 
                        "blank")

สำหรับข้อมูลเพิ่มเติมตรวจสอบ docs: http://spark.apache.org/docs/1.6.0/api/scala/#org.apache.spark.sql.DataFrame


4
ทำไมคุณถึงใช้กับคอลัมน์ตามด้วยดรอป การใช้กับคอลัมน์กับชื่อคอลัมน์เดิมง่ายกว่าหรือไม่
Ameba Spugnosa

@AmebaSpugnosa ฉันคิดว่าฉันใช้ Spark เมื่อถึงเวลาที่มันชนชื่อคอลัมน์ซ้ำ ไม่ใช่เมื่อคุณสร้างพวกเขา แต่เมื่อคุณใช้พวกเขา
msemelman

5
ไม่จำเป็นต้องวางคอลัมน์ตามด้วยการเปลี่ยนชื่อ คุณสามารถทำได้ในหนึ่งบรรทัดdf.withColumn("ctr", temp("ctr").cast(DecimalType(decimalPrecision, decimalScale)))
ruhong

1
มีการสร้างสำเนาไฟล์ข้อมูลใหม่ทั้งหมดเพื่อสร้างคอลัมน์ใหม่ในกรณีนี้หรือไม่? ฉันพลาดอะไรไปรึเปล่า? หรืออาจมีการปรับให้เหมาะสมเบื้องหลังบางฉาก?
user1814008

5
ไปตามเอกสารของSpark 2.x, df.withColumn(..)สามารถเพิ่มหรือเปลี่ยนคอลัมน์ขึ้นอยู่กับcolNameข้อโต้แย้ง
Y2K-shubham

89

[แก้ไข: มีนาคม 2016: ขอบคุณสำหรับการโหวต! แม้ว่าจริงๆนี้ไม่ได้เป็นคำตอบที่ดีที่สุดผมคิดว่าการแก้ปัญหาบนพื้นฐานwithColumn, withColumnRenamedและcastการประกวดราคาโดย msemelman มาร์ติน Senne และอื่น ๆ ที่เรียบง่ายและทำความสะอาด]

ฉันคิดว่าวิธีการของคุณนั้นโอเคจำได้ว่า Spark DataFrameเป็น RDD (ไม่เปลี่ยนรูป) ของแถวดังนั้นเราไม่เคยเปลี่ยนคอลัมน์จริงๆเพียงสร้างใหม่DataFrameทุกครั้งด้วยสคีมาใหม่

สมมติว่าคุณมี df ดั้งเดิมด้วยสคีมาดังต่อไปนี้:

scala> df.printSchema
root
 |-- Year: string (nullable = true)
 |-- Month: string (nullable = true)
 |-- DayofMonth: string (nullable = true)
 |-- DayOfWeek: string (nullable = true)
 |-- DepDelay: string (nullable = true)
 |-- Distance: string (nullable = true)
 |-- CRSDepTime: string (nullable = true)

และ UDF บางตัวถูกนิยามไว้ในคอลัมน์เดียวหรือหลายคอลัมน์:

import org.apache.spark.sql.functions._

val toInt    = udf[Int, String]( _.toInt)
val toDouble = udf[Double, String]( _.toDouble)
val toHour   = udf((t: String) => "%04d".format(t.toInt).take(2).toInt ) 
val days_since_nearest_holidays = udf( 
  (year:String, month:String, dayOfMonth:String) => year.toInt + 27 + month.toInt-12
 )

การเปลี่ยนประเภทคอลัมน์หรือแม้แต่การสร้าง DataFrame ใหม่จากอื่นสามารถเขียนดังนี้:

val featureDf = df
.withColumn("departureDelay", toDouble(df("DepDelay")))
.withColumn("departureHour",  toHour(df("CRSDepTime")))
.withColumn("dayOfWeek",      toInt(df("DayOfWeek")))              
.withColumn("dayOfMonth",     toInt(df("DayofMonth")))              
.withColumn("month",          toInt(df("Month")))              
.withColumn("distance",       toDouble(df("Distance")))              
.withColumn("nearestHoliday", days_since_nearest_holidays(
              df("Year"), df("Month"), df("DayofMonth"))
            )              
.select("departureDelay", "departureHour", "dayOfWeek", "dayOfMonth", 
        "month", "distance", "nearestHoliday")            

ซึ่งให้:

scala> df.printSchema
root
 |-- departureDelay: double (nullable = true)
 |-- departureHour: integer (nullable = true)
 |-- dayOfWeek: integer (nullable = true)
 |-- dayOfMonth: integer (nullable = true)
 |-- month: integer (nullable = true)
 |-- distance: double (nullable = true)
 |-- nearestHoliday: integer (nullable = true)

นี่ค่อนข้างใกล้กับโซลูชันของคุณเอง เพียงแค่ทำให้การเปลี่ยนแปลงประเภทและการเปลี่ยนแปลงอื่น ๆ เป็นแยกudf vals ทำให้รหัสอ่านและใช้งานได้อีก


26
สิ่งนี้ไม่ปลอดภัยหรือมีประสิทธิภาพ ไม่ปลอดภัยเนื่องจากรายการเดียวNULLหรือมีรูปแบบไม่ถูกต้องจะทำให้งานทั้งหมดล้มเหลว ไม่มีประสิทธิภาพเนื่องจาก UDF ไม่โปร่งใสสำหรับ Catalyst การใช้ UDF สำหรับการดำเนินการที่ซับซ้อนนั้นใช้ได้ แต่ก็ไม่มีเหตุผลที่จะใช้สิ่งเหล่านี้สำหรับการหล่อแบบพื้นฐาน นี่คือเหตุผลที่เรามีcastวิธี (ดูคำตอบโดย Martin Senne ) การทำให้สิ่งที่โปร่งใสแก่ตัวเร่งปฏิกิริยาต้องใช้งานมากขึ้น แต่ความปลอดภัยขั้นพื้นฐานเป็นเพียงเรื่องของการวางTryและOptionการทำงาน
zero323

ฉันไม่เห็นอะไรเกี่ยวข้องกับการแปลงสตริงเป็นวันที่เช่น "05-APR-2015"
dbspace

3
มีวิธีการลดwithColumn()ส่วนของคุณเป็นคนทั่วไปที่ iterates ผ่านคอลัมน์ทั้งหมดหรือไม่
Boern

ขอบคุณ zero323 เมื่ออ่านสิ่งนี้ฉันคิดว่าทำไมคำตอบของ udf จึงล่ม ความคิดเห็นบางส่วนจะดีกว่าคำตอบบางอย่างในดังนั้น :)
ไซมอน Dirmeier

มีวิธีใดบ้างที่เราจะได้รู้จักแถวที่เสียหายหมายถึงระเบียนที่มีคอลัมน์ประเภทข้อมูลที่ไม่ถูกต้องระหว่างการส่ง เนื่องจากฟังก์ชั่นแคสต์ทำให้ฟิลด์เหล่านั้นเป็นโมฆะ
Etisha

65

เนื่องจากการcastดำเนินการพร้อมใช้งานสำหรับ Spark Column(และเนื่องจากฉันไม่ชอบให้บุคคลudfตามที่เสนอโดย @ Svendณ จุดนี้):

df.select( df("year").cast(IntegerType).as("year"), ... )

จะส่งไปยังประเภทที่ร้องขอได้อย่างไร ในฐานะที่เป็นผลข้างเคียงที่เรียบร้อยค่าไม่ castable / "convertable" nullในแง่ที่ว่าจะกลายเป็น

ในกรณีที่คุณต้องการสิ่งนี้เป็นวิธีการช่วยเหลือให้ใช้:

object DFHelper{
  def castColumnTo( df: DataFrame, cn: String, tpe: DataType ) : DataFrame = {
    df.withColumn( cn, df(cn).cast(tpe) )
  }
}

ซึ่งใช้เหมือน:

import DFHelper._
val df2 = castColumnTo( df, "year", IntegerType )

2
คุณสามารถให้คำแนะนำฉันเกี่ยวกับวิธีการดำเนินการถ้าฉันต้องการที่จะโยนและเปลี่ยนชื่อกลุ่มของคอลัมน์ทั้งหมด (ฉันมี 50 คอลัมน์และค่อนข้างใหม่เพื่อสกาล่าไม่แน่ใจว่าวิธีที่ดีที่สุดที่จะเข้าใกล้มันโดยไม่สร้างซ้ำกันขนาดใหญ่)? บางคอลัมน์ควรอยู่ที่ String บางอันควรถูกส่งไปยังโฟลต
Dmitry Smirnov

วิธีการแปลงสตริงเป็นวันที่ตัวอย่างเช่น "25-APR-2016" ในคอลัมน์และ "20160302"
dbspace

@DmitrySmirnov คุณเคยได้รับคำตอบบ้างไหม? ฉันมีคำถามเดียวกัน ;)
Evan Zamir

@EvanZamir โชคไม่ดีฉันลงเอยด้วยการทำ shitton เพื่อให้สามารถใช้ข้อมูลเป็น rdd ในขั้นตอนอื่นได้ ฉันสงสัยว่านี้กลายเป็นเรื่องง่ายวันนี้ :)
มิทรีนอฟ

60

ก่อนอื่นถ้าคุณต้องการประเภทนักแสดงแล้วนี่:

import org.apache.spark.sql
df.withColumn("year", $"year".cast(sql.types.IntegerType))

ด้วยชื่อคอลัมน์เดียวกันคอลัมน์จะถูกแทนที่ด้วยชื่อใหม่ คุณไม่จำเป็นต้องทำการเพิ่มและลบขั้นตอน

ประการที่สองเกี่ยวกับสกาล่า VS R
นี่คือรหัสที่คล้ายกับ RI มากที่สุด:

val df2 = df.select(
   df.columns.map {
     case year @ "year" => df(year).cast(IntegerType).as(year)
     case make @ "make" => functions.upper(df(make)).as(make)
     case other         => df(other)
   }: _*
)

แม้ว่าความยาวรหัสจะยาวกว่าของ R เล็กน้อย นั่นไม่เกี่ยวกับการใช้คำฟุ่มเฟือยของภาษา ใน R the mutateเป็นฟังก์ชั่นพิเศษสำหรับ R dataframe ในขณะที่ใน Scala คุณสามารถ ad-hoc ได้อย่างง่ายดายด้วยพลังแห่งการแสดงออก
ในคำมันหลีกเลี่ยงการแก้ปัญหาเฉพาะเพราะการออกแบบภาษาที่ดีพอสำหรับคุณที่จะสร้างภาษาโดเมนของคุณเองได้ง่ายและรวดเร็ว


ด้านหมายเหตุ: df.columnsเป็นที่น่าแปลกใจArray[String]แทนArray[Column]บางทีพวกเขาต้องการให้ดูเหมือนว่าดาต้าดาต้าของงูหลาม


1
คุณช่วยให้เทียบเท่ากับ pyspark ได้ไหม?
Harit Vishwakarma

ฉันได้รับ "คำจำกัดความที่ผิดกฎหมายเริ่มต้น" .withColumn ("อายุ", $ "อายุ" .cast (sql.types.DoubleType)) สำหรับฟิลด์ "อายุ" ของฉัน ข้อเสนอแนะใด ๆ
BlueDolphin

คุณต้องใช้. cache () เฟรมข้อมูลหรือไม่หากเราทำการแปลงเหล่านี้ในหลาย ๆ คอลัมน์เพื่อเหตุผลด้านประสิทธิภาพหรือไม่เป็นสิ่งจำเป็นเนื่องจาก Spark จะปรับให้เหมาะสมหรือไม่
skjagini

การนำเข้าสามารถimport org.apache.spark.sql.types._แล้วแทนที่จะเป็นเพียงแค่sql.types.IntegerType IntegerType
nessa.gp

17

คุณสามารถใช้selectExprเพื่อทำให้มันสะอาดขึ้นเล็กน้อย:

df.selectExpr("cast(year as int) as year", "upper(make) as make",
    "model", "comment", "blank")

14

รหัส Java สำหรับการปรับเปลี่ยนประเภทข้อมูลของ DataFrame จาก String เป็น Integer

df.withColumn("col_name", df.col("col_name").cast(DataTypes.IntegerType))

มันก็จะส่งที่มีอยู่ (ประเภทข้อมูลสตริง) เพื่อจำนวนเต็ม


1
ไม่มีDataTypesในsql.types! DataTypeมันเป็น นอกจากนี้เราสามารถนำเข้าIntegerTypeและส่งได้อย่างง่ายดาย
Ehsan M. Kermani

@ EhsanM.Kermani จริง ๆ แล้ว DatyaTypes.IntegerType เป็นการอ้างอิงที่ถูกต้อง
Cupitor

1
@Cupitor DataTypes.IntegerTypeเคยอยู่ในโหมด DeveloperAPIและมีเสถียรภาพใน v.2.1.0
Ehsan M. Kermani

นี่คือทางออกที่ดีที่สุด!
Simon Dirmeier

8

ในการแปลงปีจากสตริงเป็น int คุณสามารถเพิ่มตัวเลือกต่อไปนี้ในโปรแกรมอ่าน csv: "inferSchema" -> "true" ดูเอกสารประกอบ DataBricks


5
วิธีนี้ใช้งานได้ดี แต่การจับคือผู้อ่านต้องทำไฟล์ที่สองของคุณ
beefyhalo

@Beefyhalo มีจุดอยู่อย่างนั้นมีวิธีใดบ้างไหม?
Ayush

6

ดังนั้นวิธีนี้จะใช้งานได้จริงถ้าคุณมีปัญหาในการบันทึกไปยังไดร์เวอร์ jdbc เช่น sqlserver แต่มันมีประโยชน์มากสำหรับข้อผิดพลาดที่คุณจะพบกับไวยากรณ์และประเภท

import org.apache.spark.sql.jdbc.{JdbcDialects, JdbcType, JdbcDialect}
import org.apache.spark.sql.jdbc.JdbcType
val SQLServerDialect = new JdbcDialect {
  override def canHandle(url: String): Boolean = url.startsWith("jdbc:jtds:sqlserver") || url.contains("sqlserver")

  override def getJDBCType(dt: DataType): Option[JdbcType] = dt match {
    case StringType => Some(JdbcType("VARCHAR(5000)", java.sql.Types.VARCHAR))
    case BooleanType => Some(JdbcType("BIT(1)", java.sql.Types.BIT))
    case IntegerType => Some(JdbcType("INTEGER", java.sql.Types.INTEGER))
    case LongType => Some(JdbcType("BIGINT", java.sql.Types.BIGINT))
    case DoubleType => Some(JdbcType("DOUBLE PRECISION", java.sql.Types.DOUBLE))
    case FloatType => Some(JdbcType("REAL", java.sql.Types.REAL))
    case ShortType => Some(JdbcType("INTEGER", java.sql.Types.INTEGER))
    case ByteType => Some(JdbcType("INTEGER", java.sql.Types.INTEGER))
    case BinaryType => Some(JdbcType("BINARY", java.sql.Types.BINARY))
    case TimestampType => Some(JdbcType("DATE", java.sql.Types.DATE))
    case DateType => Some(JdbcType("DATE", java.sql.Types.DATE))
    //      case DecimalType.Fixed(precision, scale) => Some(JdbcType("NUMBER(" + precision + "," + scale + ")", java.sql.Types.NUMERIC))
    case t: DecimalType => Some(JdbcType(s"DECIMAL(${t.precision},${t.scale})", java.sql.Types.DECIMAL))
    case _ => throw new IllegalArgumentException(s"Don't know how to save ${dt.json} to JDBC")
  }
}

JdbcDialects.registerDialect(SQLServerDialect)

คุณสามารถช่วยฉันใช้รหัสเดียวกันใน Java ได้หรือไม่? และวิธีการลงทะเบียน customJdbcDialect ใน DataFrame
abhijitcaps

เป็นคนดีฉันทำแบบเดียวกันกับ Vertica แต่ตั้งแต่เป็นประกาย 2.1 JDbcUtil คุณต้องใช้ประเภทข้อมูลเฉพาะที่คุณต้องการ dialect.getJDBCType (dt) .orElse (getCommonJDBCType (dt)) getOrElse (โยน IllegalArgumentException ใหม่ ("ไม่สามารถรับประเภท JDBC สำหรับ $ {dt.simpleString}")
Arnon Rodman

6

สร้างชุดข้อมูลอย่างง่ายที่มีห้าค่าและแปลงintเป็นstringประเภท:

val df = spark.range(5).select( col("id").cast("string") )

6

ฉันคิดว่านี่เป็นสิ่งที่อ่านได้มากขึ้นสำหรับฉัน

import org.apache.spark.sql.types._
df.withColumn("year", df("year").cast(IntegerType))

สิ่งนี้จะแปลงคอลัมน์ปีของคุณเป็นIntegerTypeด้วยการสร้างคอลัมน์ชั่วคราวและวางคอลัมน์เหล่านั้น หากคุณต้องการแปลงเป็นประเภทข้อมูลอื่นคุณสามารถตรวจสอบประเภทภายในorg.apache.spark.sql.typesแพ็คเกจได้


5

คำตอบที่แนะนำให้ใช้ cast, FYI, วิธีการร่ายใน spark 1.4.1 นั้นใช้ไม่ได้

ตัวอย่างเช่น dataframe ที่มีคอลัมน์สตริงที่มีค่า "8182175552014127960" เมื่อ cast ไปที่ bigint มีค่า "8182175552014128100"

    df.show
+-------------------+
|                  a|
+-------------------+
|8182175552014127960|
+-------------------+

    df.selectExpr("cast(a as bigint) a").show
+-------------------+
|                  a|
+-------------------+
|8182175552014128100|
+-------------------+

เราต้องเผชิญกับปัญหามากมายก่อนที่จะพบข้อผิดพลาดนี้เพราะเรามีคอลัมน์ขนาดใหญ่ในการผลิต


4
psst อัพเกรด spark ของคุณ
msemelman

2
@msemelman มันไร้สาระที่จะต้องอัพเกรดเป็นเวอร์ชั่นใหม่ของประกายไฟในการผลิตสำหรับข้อบกพร่องเล็ก ๆ
sauraI3h

เราไม่อัปเกรดทุกสิ่งเป็นข้อบกพร่องเล็ก ๆ เสมอหรือไม่ :)
caesarsol



3

คุณสามารถใช้รหัสด้านล่าง

df.withColumn("year", df("year").cast(IntegerType))

ซึ่งจะแปลงคอลัมน์ปีเป็นIntegerTypeคอลัมน์


2

วิธีนี้จะวางคอลัมน์เก่าและสร้างคอลัมน์ใหม่ด้วยค่าเดียวกันและประเภทข้อมูลใหม่ ประเภทข้อมูลเดิมของฉันเมื่อสร้าง DataFrame คือ: -

root
 |-- id: integer (nullable = true)
 |-- flag1: string (nullable = true)
 |-- flag2: string (nullable = true)
 |-- name: string (nullable = true)
 |-- flag3: string (nullable = true)

หลังจากนี้ฉันรันโค้ดต่อไปนี้เพื่อเปลี่ยนประเภทข้อมูล: -

df=df.withColumnRenamed(<old column name>,<dummy column>) // This was done for both flag1 and flag3
df=df.withColumn(<old column name>,df.col(<dummy column>).cast(<datatype>)).drop(<dummy column>)

หลังจากนี้ผลลัพธ์ของฉันออกมาเป็น: -

root
 |-- id: integer (nullable = true)
 |-- flag2: string (nullable = true)
 |-- name: string (nullable = true)
 |-- flag1: boolean (nullable = true)
 |-- flag3: boolean (nullable = true)

คุณช่วยแก้ปัญหาของคุณที่นี่ได้ไหม
Ajay Kharade

1

หนึ่งสามารถเปลี่ยนชนิดข้อมูลของคอลัมน์โดยใช้ cast ใน spark sql ชื่อตารางคือตารางและมีสองคอลัมน์เท่านั้นที่จะเปลี่ยนประเภทข้อมูลคอลัมน์ 1 และคอลัมน์ 2 และคอลัมน์ 1 ex-spark.sql ("เลือก cast (column1 เป็น Double) column1NewName, column2 จาก table") แทนการเขียน double data ของคุณ


1

ในกรณีที่คุณต้องเปลี่ยนชื่อคอลัมน์หลายสิบชื่อตามตัวอย่างต่อไปนี้ใช้แนวทางของ @dnlbrky และนำไปใช้กับหลายคอลัมน์ในครั้งเดียว:

df.selectExpr(df.columns.map(cn => {
    if (Set("speed", "weight", "height").contains(cn)) s"cast($cn as double) as $cn"
    else if (Set("isActive", "hasDevice").contains(cn)) s"cast($cn as boolean) as $cn"
    else cn
}):_*)

คอลัมน์ที่ไม่ได้คาสต์จะถูกเก็บไว้เหมือนเดิม คอลัมน์ทั้งหมดยังคงอยู่ในลำดับเดิม


1

คำตอบมากมายและคำอธิบายที่ไม่ละเอียดมากนัก

ไวยากรณ์ต่อไปนี้ใช้งานได้โดยใช้ Databricks Notebook with Spark 2.4

from pyspark.sql.functions import *
df = df.withColumn("COL_NAME", to_date(BLDFm["LOAD_DATE"], "MM-dd-yyyy"))

โปรดทราบว่าคุณต้องระบุรูปแบบรายการที่คุณมี (ในกรณีของฉัน "MM-dd-yyyy") และการนำเข้ามีผลบังคับใช้เนื่องจาก to_date เป็นฟังก์ชัน spark sql

ลองไวยากรณ์นี้ แต่ได้รับโมฆะแทนการโยนที่เหมาะสม:

df = df.withColumn("COL_NAME", df["COL_NAME"].cast("Date"))

(หมายเหตุฉันต้องใช้เครื่องหมายวงเล็บและเครื่องหมายคำพูดเพื่อให้ถูกต้องตามหลักไวยากรณ์)


PS: ฉันต้องยอมรับว่านี่เป็นเหมือนไวยกรณ์ไวยากรณ์มีจุดเริ่มต้นที่เป็นไปได้หลายวิธีและการอ้างอิง API อย่างเป็นทางการขาดตัวอย่างที่เหมาะสม


1
ป่าซินแท็คซ์ ใช่. นี่คือโลกของ Spark ตอนนี้
conner.xyz

1

แนวทางแก้ไขอื่นมีดังนี้:

1) เก็บ "inferSchema" เป็นเท็จ

2) ขณะที่เรียกใช้ฟังก์ชัน 'แผนที่' ในแถวคุณสามารถอ่าน 'asString' (row.getString ... )

//Read CSV and create dataset
Dataset<Row> enginesDataSet = sparkSession
            .read()
            .format("com.databricks.spark.csv")
            .option("header", "true")
            .option("inferSchema","false")
            .load(args[0]);

JavaRDD<Box> vertices = enginesDataSet
            .select("BOX","BOX_CD")
            .toJavaRDD()
            .map(new Function<Row, Box>() {
                @Override
                public Box call(Row row) throws Exception {
                    return new Box((String)row.getString(0),(String)row.get(1));
                }
            });


0
    val fact_df = df.select($"data"(30) as "TopicTypeId", $"data"(31) as "TopicId",$"data"(21).cast(FloatType).as( "Data_Value_Std_Err")).rdd
    //Schema to be applied to the table
    val fact_schema = (new StructType).add("TopicTypeId", StringType).add("TopicId", StringType).add("Data_Value_Std_Err", FloatType)

    val fact_table = sqlContext.createDataFrame(fact_df, fact_schema).dropDuplicates()

0

อีกวิธีหนึ่ง:

// Generate a simple dataset containing five values and convert int to string type

val df = spark.range(5).select( col("id").cast("string")).withColumnRenamed("id","value")

0

ในกรณีที่คุณต้องการเปลี่ยนคอลัมน์หลายคอลัมน์ให้เป็นประเภทอื่นโดยไม่ระบุชื่อคอลัมน์

/* Get names of all columns that you want to change type. 
In this example I want to change all columns of type Array to String*/
    val arrColsNames = originalDataFrame.schema.fields.filter(f => f.dataType.isInstanceOf[ArrayType]).map(_.name)

//iterate columns you want to change type and cast to the required type
val updatedDataFrame = arrColsNames.foldLeft(originalDataFrame){(tempDF, colName) => tempDF.withColumn(colName, tempDF.col(colName).cast(DataTypes.StringType))}

//display

updatedDataFrame.show(truncate = false)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.