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