0

選擇專欄中,我要實現以下的事情
比如我的Emp文件的(2個文件) 我只需要選擇2例如EMPID和EmpName列,如果文件不具有EmpName它應選擇EMPID數據幀星火數據框中使用情況

1)Emp1.csv(文件)

Empid EmpName Dept 
1  ABC  IS 
2  XYZ  COE 

2)Emp.csv(文件)

Empid EmpName 
1  ABC 
2  XYZ 
0的一列

代碼試圖到目前爲止

scala> val SourceData = spark.read.format("com.databricks.spark.csv").option("inferSchema", "true").option("delimiter", ",").option("header", "true").load("/root/Empfiles/") 
SourceData: org.apache.spark.sql.DataFrame = [Empid: string, EmpName: string ... 1 more field] 

scala> SourceData.printSchema 
root 
|-- Empid: string (nullable = true) 
|-- EmpName: string (nullable = true) 
|-- Dept: string (nullable = true) 

如果指定文件

scala> var FormatedColumn = SourceData.select(
|    SourceData.columns.map { 
| case "Empid"      => SourceData("Empid").cast(IntegerType).as("empid") 
| case "EmpName"      => SourceData("EmpName").cast(StringType).as("empname") 
| case "Dept"      => SourceData("Dept").cast(StringType).as("dept") 
| }: _* 
|) 
FormatedColumn: org.apache.spark.sql.DataFrame = [empid: int, empname: string ... 1 more field] 

的所有列名,但我想只有特定的兩列失敗(如果列可顯示它選擇與此代碼工作更改數據類型和列名稱)

scala> var FormatedColumn = SourceData.select(
| SourceData.columns.map { 
| case "Empid"      => SourceData("Empid").cast(IntegerType).as("empid") 
| case "EmpName"      => SourceData("EmpName").cast(StringType).as("empname") 
| }: _* 
|) 
scala.MatchError: Dept (of class java.lang.String) 
at $anonfun$1.apply(<console>:32) 
at $anonfun$1.apply(<console>:32) 
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) 
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) 
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) 
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186) 
at scala.collection.TraversableLike$class.map(TraversableLike.scala:234) 
at scala.collection.mutable.ArrayOps$ofRef.map(ArrayOps.scala:186) 
    ... 53 elided 
+0

它拋出一個MatchError,因爲它無法在您的映射函數中找到匹配的大小寫。如果您添加一個默認情況下它應該成功。您也可以首先在「Empid」和「EmpName」上運行選擇,然後格式化後續列。 –

+0

對不起,我是新來的默認情況下,斯卡拉我不想做任何事,所以我應該寫什麼? – Bhavesh

回答

1

所有其他列也需要匹配:

var formattedColumn = sourceData.select(
    sourceData.columns.map { 
     case "Empid" => sourceData("Empid").cast(IntegerType).as("empid") 
     case "EmpName" => sourceData("EmpName").cast(StringType).as("empname") 
     case other: String => sourceData(other) 
    }: _* 
) 

更新1。如果你想只選擇兩列「EMPID」和「EmpName」,也沒有必要使用匹配:

val formattedColumn = sourceData.select(
    sourceData("Empid").cast(IntegerType).as("empid"), 
    sourceData("EmpName").cast(StringType).as("empname") 
) 

更新2。如果要根據它們的存在選擇列,我可以提出以下建議:

val colEmpId = "Empid" 
val colEmpName = "EmpName" 
// list of possible expected column names 
val selectableColums = Seq(colEmpId, colEmpName) 
// take only the ones that are in the list 
val foundColumns = sourceData.columns.filter(column => selectableColums.contains(column)) 
// create the target dataframe 
val formattedColumn = sourceData.select(
    foundColumns.map(column => 
    column match { 
     case colEmpId => sourceData(colEmpId).cast(IntegerType).as("empid") 
     case colEmpName => sourceData(colEmpName).cast(StringType).as("empname") 
     case _ => throw new IllegalArgumentException("Unexpected column: " + column) 
    } 
): _* 
) 

p.s.請使用val s和var s的傳統camelCase名稱。

+0

斯卡拉> FormattedColumn.printSchema 根 | - EMPID:整數(可爲空=真) | - empname:字符串(可爲空=真) | - 部:字符串(可爲空=真)我不想選擇部門在格式化列數據框我只想要2列 – Bhavesh

+0

@Bhavesh,我更新了這個案例的答案。 – Antot

+0

如果文件沒有EmpName,它不會運行,它應該選擇一列Empid數據幀,在這種情況下它將失敗 – Bhavesh

0

如果你用這個查詢替換你的語句,它應該工作。 它過濾掉所有不屬於你的match子句的列。這可以避免你看到的MatchError。

df.select($"Empid", $"EmpName").select(df.columns.map { 
    case "Empid" => df("Empid").cast(IntegerType).as("empid") 
    case "EmpName" => df("EmpName").cast(StringType).as("empname") 
}: _*) 
+0

不,它不工作我已經嘗試過您的代碼:32:錯誤:重載的方法值選擇與替代品: 不能應用於(Array [org。 (df.columns.map { – Bhavesh

+0

我猜我缺少「:_ *」。 –

+0

if file doesn' t有EmpName它應該選擇一列Empid數據框我不認爲它滿足這個 – Bhavesh

0

我不知道爲什麼它是這個複雜..

爲什麼不這樣做呢?

df 
    .withColumn("empid", $"EmpId".cast(IntegerType)) 
    .withColumn("empname", $"EmpName".cast(StringType))