2016-11-30 19 views
10

Đó là CDH với Spark 1.6.Đọc CSV vào một Khung dữ liệu Spark có dấu thời gian và các loại ngày

Tôi cố gắng để nhập CSV Giả định này thành một DataFrame apache Spark:

$ hadoop fs -cat test.csv 
a,b,c,2016-09-09,a,2016-11-11 09:09:09.0,a 
a,b,c,2016-09-10,a,2016-11-11 09:09:10.0,a 

tôi sử dụng databricks-csv jar.

val textData = sqlContext.read 
    .format("com.databricks.spark.csv") 
    .option("header", "false") 
    .option("delimiter", ",") 
    .option("dateFormat", "yyyy-MM-dd HH:mm:ss") 
    .option("inferSchema", "true") 
    .option("nullValue", "null") 
    .load("test.csv") 

Tôi sử dụng suy luậnSchema để tạo giản đồ cho DataFrame kết quả. printSchema() chức năng mang lại cho tôi đầu ra sau đây cho đoạn code trên:

scala> textData.printSchema() 
root 
|-- C0: string (nullable = true) 
|-- C1: string (nullable = true) 
|-- C2: string (nullable = true) 
|-- C3: string (nullable = true) 
|-- C4: string (nullable = true) 
|-- C5: timestamp (nullable = true) 
|-- C6: string (nullable = true) 

scala> textData.show() 
+---+---+---+----------+---+--------------------+---+ 
| C0| C1| C2|  C3| C4|     C5| C6| 
+---+---+---+----------+---+--------------------+---+ 
| a| b| c|2016-09-09| a|2016-11-11 09:09:...| a| 
| a| b| c|2016-09-10| a|2016-11-11 09:09:...| a| 
+---+---+---+----------+---+--------------------+---+ 

Cột C3 có Chuỗi loại. Tôi muốn C3 có ngày loại. Để có được nó cho đến nay loại tôi đã thử đoạn mã sau.

val textData = sqlContext.read.format("com.databricks.spark.csv") 
    .option("header", "false") 
    .option("delimiter", ",") 
    .option("dateFormat", "yyyy-MM-dd") 
    .option("inferSchema", "true") 
    .option("nullValue", "null") 
    .load("test.csv") 

scala> textData.printSchema 
root 
|-- C0: string (nullable = true) 
|-- C1: string (nullable = true) 
|-- C2: string (nullable = true) 
|-- C3: timestamp (nullable = true) 
|-- C4: string (nullable = true) 
|-- C5: timestamp (nullable = true) 
|-- C6: string (nullable = true) 

scala> textData.show() 
+---+---+---+--------------------+---+--------------------+---+ 
| C0| C1| C2|     C3| C4|     C5| C6| 
+---+---+---+--------------------+---+--------------------+---+ 
| a| b| c|2016-09-09 00:00:...| a|2016-11-11 00:00:...| a| 
| a| b| c|2016-09-10 00:00:...| a|2016-11-11 00:00:...| a| 
+---+---+---+--------------------+---+--------------------+---+ 

Sự khác biệt duy nhất giữa mã này và khối đầu tiên là DateFormat tùy chọn dòng (tôi sử dụng "yyyy-MM-dd" thay vì "yyyy-MM-dd HH: mm: ss "). Bây giờ tôi có cả C3 và C5 là dấu thời gian (C3 vẫn chưa có ngày). Nhưng đối với C5, phần HH :: mm: ss bị bỏ qua và hiển thị dưới dạng số 0 trong dữ liệu.

Lý tưởng nhất là tôi muốn C3 có loại ngày, C5 là loại dấu thời gian và phần HH: mm: ss không bị bỏ qua. Giải pháp của tôi ngay bây giờ trông như thế này. Tôi làm cho csv bằng cách kéo dữ liệu song song với DB của tôi. Tôi chắc chắn rằng tôi kéo tất cả các ngày như timestamps (Không lý tưởng). Vì vậy, csv thử nghiệm trông như thế này bây giờ:

$ hadoop fs -cat new-test.csv 
a,b,c,2016-09-09 00:00:00,a,2016-11-11 09:09:09.0,a 
a,b,c,2016-09-10 00:00:00,a,2016-11-11 09:09:10.0,a 

Đây là mã làm việc cuối cùng của tôi:

val textData = sqlContext.read.format("com.databricks.spark.csv") 
    .option("header", "false") 
    .option("delimiter", ",") 
    .option("dateFormat", "yyyy-MM-dd HH:mm:ss") 
    .schema(finalSchema) 
    .option("nullValue", "null") 
    .load("new-test.csv") 

Ở đây, tôi sử dụng định dạng timestamp đầy đủ ("yyyy-MM-dd HH: mm : ss ") trong dateFormat. Tôi tự tạo ra thể hiện finalSchema trong đó c3 là ngày và C5 là kiểu dấu thời gian (kiểu sql Spark). Tôi áp dụng các lược đồ này sử dụng hàm schema(). Kết quả trông giống như sau:

scala> finalSchema 
res4: org.apache.spark.sql.types.StructType = StructType(StructField(C0,StringType,true), StructField(C1,StringType,true), StructField(C2,StringType,true), StructField(C3,DateType,true), StructField(C4,StringType,true), StructField(C5,TimestampType,true), StructField(C6,StringType,true)) 

scala> textData.printSchema() 
root 
|-- C0: string (nullable = true) 
|-- C1: string (nullable = true) 
|-- C2: string (nullable = true) 
|-- C3: date (nullable = true) 
|-- C4: string (nullable = true) 
|-- C5: timestamp (nullable = true) 
|-- C6: string (nullable = true) 


scala> textData.show() 
+---+---+---+----------+---+--------------------+---+ 
| C0| C1| C2|  C3| C4|     C5| C6| 
+---+---+---+----------+---+--------------------+---+ 
| a| b| c|2016-09-09| a|2016-11-11 09:09:...| a| 
| a| b| c|2016-09-10| a|2016-11-11 09:09:...| a| 
+---+---+---+----------+---+--------------------+---+ 

Có một dễ dàng hơn hoặc ra khỏi con đường hộp để phân tích ra một tập tin csv (có cả ngày và timestamp loại thành một dataframe spark

Liên kết liên quan? :
http://spark.apache.org/docs/latest/sql-programming-guide.html#manually-specifying-options
https://github.com/databricks/spark-csv

Trả lời

1

với một lựa chọn suy luận đối với trường hợp không tầm thường nó có thể sẽ không trả lại kết quả mong đợi Như bạn có thể thấy trong.:

if (field == null || field.isEmpty || field == nullValue) { 
    typeSoFar 
} else { 
    typeSoFar match { 
    case NullType => tryParseInteger(field) 
    case IntegerType => tryParseInteger(field) 
    case LongType => tryParseLong(field) 
    case DoubleType => tryParseDouble(field) 
    case TimestampType => tryParseTimestamp(field) 
    case BooleanType => tryParseBoolean(field) 
    case StringType => StringType 
    case other: DataType => 
     throw new UnsupportedOperationException(s"Unexpected data type $other") 

Nó sẽ chỉ cố gắng để phù hợp với mỗi cột với một loại dấu thời gian, không phải là một loại ngày, do đó "ra khỏi các giải pháp hộp" cho trường hợp này là không thể.Nhưng với kinh nghiệm của tôi giải pháp "dễ dàng hơn", trực tiếp xác định lược đồ với needed type, nó sẽ tránh tùy chọn suy luận thiết lập một loại chỉ phù hợp với RDD được đánh giá không phải toàn bộ dữ liệu. Lược đồ cuối cùng của bạn là một giải pháp hiệu quả.

Các vấn đề liên quan