2017-07-13 51 views
1

通過給出更多詳細信息,重新構建了該問題。Spark Scala中從字符串到日期的轉換

我有一個數據幀「dailyshow」架構是:

scala> dailyshow.printSchema 
root 
|-- year: integer (nullable = true) 
|-- occupation: string (nullable = true) 
|-- showdate: string (nullable = true) 
|-- group: string (nullable = true) 
|-- guest: string (nullable = true) 

樣本數據是:

scala> dailyshow.show(5) 
+----+------------------+---------+------+----------------+ 
|year|  occupation| showdate| group|   guest| 
+----+------------------+---------+------+----------------+ 
|1999|    actor|1/11/1999|Acting| Michael J. Fox| 
|1999|   Comedian|1/12/1999|Comedy| Sandra Bernhard| 
|1999|television actress|1/13/1999|Acting| Tracey Ullman| 
|1999|  film actress|1/14/1999|Acting|Gillian Anderson| 
|1999|    actor|1/18/1999|Acting|David Alan Grier| 
+----+------------------+---------+------+----------------+ 

下面碼被用於轉化和產生該返回的時間之間的頂部5的職業結果期間「01/11/1999」和「06/11/1999」

scala> dailyshow. 
    withColumn("showdate",to_date(unix_timestamp(col("showdate"),"MM/dd/yyyy"). 
    cast("timestamp"))). 
    where((col("showdate") >= "1999-01-11") and (col("showdate") <= "1999-06-11")). 
    groupBy(col("occupation")).agg(count("*").alias("count")). 
    orderBy(desc("count")). 
    limit(5).show 
     +------------------+-----+              
     |  occupation|count| 
     +------------------+-----+ 
     |    actor| 29| 
     |   actress| 20| 
     |   comedian| 4| 
     |television actress| 3| 
     | stand-up comedian| 2| 
     +------------------+-----+ 

我的問題我當使用RDD時如何編碼並得到相同的結果?

scala> dailyshow.first 
res12: org.apache.spark.sql.Row = [1999,actor,1/11/1999,Acting,Michael J. Fox] 

我用SimpleDateFormat解析字符串到日期的DataFrame

下面是代碼:

val format = new java.text.SimpleDateFormat("MM/dd/yyyy") 

dailyshow. 
    map(x => x.mkString(",")). 
    map(x => x.split(",")). 
    map(x => format.parse(x(2))).first // returns Mon Jan 11 00:00:00 PST 1999 
+0

是什麼'dailyshow'包含哪些內容?你的前兩張地圖看起來像是互相取消了。 – philantrovert

+0

@philantrovert dailyshow是一個數據框。 前2個映射表用於將DF轉換爲RDD,因爲DF以「[」開頭並以「]」結尾。 。爲了避免提取這2個字符,使用前兩個地圖。 – Jayson

+0

'datashow'中的示例數據和預期輸出將對回答者有很大的幫助。如果可以,請添加,謝謝。 – philantrovert

回答

0

獲得大量棄用警告,而寫這本:d

所以我們有這個數據在RDD

val rdd = sc.parallelize(Array(
    Array("1999","actor","1/11/1999","Acting"," Michael J. Fox"), 
    Array("1999","Comedian","1/12/1999","Comedy"," Sandra Bernhard"), 
    Array("1999","television actress","1/13/1999","Acting","Tracey Ullman"), 
    Array("1999","film actress","1/14/1999","Acting","Gillian Anderson"), 
    Array("1999","actor","1/18/1999","Acting","David Alan Grier"))) 

然後根據您的問題,我們做一個過濾器上的日期:

val filtered = rdd.filter{ x => 
    format.parse(x(2)).after(new java.util.Date("01/10/1999")) && 
    format.parse(x(2)).before(new java.util.Date("01/14/1999")) 
} 

然後我們得到這個:

Array[Array[String]] = Array(
Array(1999, actor, 1/11/1999, Acting, " Michael J. Fox"), 
Array(1999, Comedian, 1/12/1999, Comedy, " Sandra Bernhard"), 
Array(1999, television actress, 1/13/1999, Acting, Tracey Ullman)) 

然後我們組他們的第二個元素爲重點,並計算出現的次數:

filtered.keyBy(x => x(1)).map((_, 1)).reduceByKey(_+_).map{ case ((a, b) ,c) => (a,c) } 

如果一切發展順利,你應該得到:

Array[(String, Int)] = Array((television actress,1), (Comedian,1), (actor,1)) 
+0

感謝它的工作......但我修改了分組代碼。使用下面的一個。 'filtered.map(x =>(x(1),1))。reduceByKey(_ + _)。take(5)' – Jayson

+0

太好了。這更好,也更簡單。 – philantrovert

0

如果我是你,我會用在org.apache.spark.sql.functions有簡單和映射定義,而不是做手工自己火花的內部日期函數。這是因爲使用數據框函數更簡單,更習慣,不易出錯並且性能更好。

假設您有一個dataframe df,其中有一個名爲dateString的列,其中包含格式爲MM/dd/yyyy的日期字符串。

讓我們假設你想將其轉換爲一個日期,以便提取一年,然後在格式顯示它yyyy.MMMMM.dd

你可以做的是:

val dfWithDate = df.withColumn("date", to_date($"dateString") 
val dfWithYear = dfWithDate.withColumn("year", year($"date")) 
val dfWithOutput = dfWithYear.withColumn("dateOutput", date_format("$date", "yyyy.MMMMM.dd") 

現在年份列將包含年份,dateOutput列將包含您的格式的字符串表示。

+0

感謝您的回覆。但我正在研究RDD。這些函數不適用於RDD – Jayson

+0

@Jayson從數據框開始,將其轉換爲RDD。爲什麼需要直接在開始時這樣做?如果您提供了一個更爲全面的例子(即原始數據框的一些輸入示例以及您計劃如何使用結果),那麼可以改進 –

+0

我已經重新構建了這個問題。請幫助 – Jayson