如何使用SparkR取消数据?

时间:2016-07-27 00:58:42

标签: r apache-spark hive sparkr

使用SparkR嵌套数组如何“爆炸”?我已经尝试使用explode,如此:

 dat <- nested_spark_df %>% 
     mutate(a=explode(metadata)) %>%
     head()

但是虽然上面的内容不会引发异常,但它不会将metadata中的嵌套字段提升到顶层。基本上我在寻求类似于Hive的LATERAL VIEW explode()功能的行为,而不依赖于HiveContext

请注意,在代码段中我使用通过SparkRext启用的NSE。我认为等效的直线 - SparkR类似于... %>% mutate(a=explode(nested_spark_df$metadata)) ...或类似的东西。

修改

我尝试在LATERAL VIEW explode(...)函数中使用SparkR::sql。它似乎适用于Parquet和ORC数据。但是,在使用嵌套的Avro数据时,我尝试了:

dat <- collect(sql(HiveContext,
                   paste0("SELECT a.id, ax.arrival_airport, x.arrival_runway ",
                          "FROM avrodb.flight a ",  
                             "LATERAL VIEW explode(a.metadata) a AS ax ",
                          "WHERE ax.arrival_airport='ATL'")))

只是为了获得以下错误,但是当avrodbparquetdb交换包含等效数据时,它会按照我的预期进行操作。

Error in invokeJava(isStatic = TRUE, className, methodName, ...) :
  org.apache.spark.SparkException: Job aborted due to stage failure: Task 4 in stage 5.0 failed 4 times, most recent failure: Lost task 4.3 in stage 5.0 (TID 1345, dev-dn04.myorg.org): org.apache.avro.AvroTypeException: Found metadata, expecting union
    at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:292)
    at org.apache.avro.io.parsing.Parser.advance(Parser.java:88)
    at org.apache.avro.io.ResolvingDecoder.readIndex(ResolvingDecoder.java:267)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:155)
    at org.apache.avro.generic.GenericDatumReader.readArray(GenericDatumReader.java:219)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:153)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:155)
    at org.apache.avro.generic.GenericDatumReader.readField(GenericDatumReader.java:193)
    at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:183)
    at org.apache.avr
Calls: <Anonymous> ... collect -> collect -> .local -> callJStatic -> invokeJava

尽管我在启动Spark时加入了DataBricks Avro软件包。使用SQLContext(而不是HiveContext)使用spark读取相同数据的工作正常,但我无法弄清楚如何有效地使用explode()函数。我还通过使用我尝试与SparkR::sql(HiveContext, hql)

运行的相同HQL语句成功通过Hive查询相同的文件来确认这不是数据本身的问题

2 个答案:

答案 0 :(得分:1)

非常感谢@Sim。我终于想出了一个理智的方法。关键是在explode操作之后,当所有爆炸值仍然嵌套在一个深度时,必须执行select。例如:

dat <- nested_spark_df %>% 
 mutate(a=explode(nested_spark_df$metadata)) %>%
 select("id", "a.fld1", "a.fld2")

这将导致SparkR DataFrame对象包含3列:idfld1fld2(前{no a.)。

我的心理障碍是我试图像PIG的flatten一样爆炸,它会在架构的顶层创建一堆新的字段名称。

答案 1 :(得分:0)

此时,使用dplyr中的数组列很棘手,例如,请参阅this issue。可能最好通过Spark使用explode()。另请注意,使用explode的DSL版本会产生开销(请参阅this answer),因此您可能希望通过sql()使用SQL表单。