web-dev-qa-db-ja.com

Sparklyrパッケージを使用してさまざまなデータ型のデータをフラット化するにはどうすればよいですか?

はじめに

Rコードは、Sparklyrパッケージを使用してデータベーススキーマを作成することによって記述されます。 [再現可能なコードとデータベースが提供されます]

既存の結果

_root
|-- contributors : string
|-- created_at : string
|-- entities (struct)
|     |-- hashtags (array) : [string]
|     |-- media (array)
|     |     |-- additional_media_info (struct)
|     |     |       |-- description : string
|     |     |       |-- embeddable : boolean
|     |     |       |-- monetizable : bollean
|     |     |-- diplay_url : string
|     |     |-- id : long
|     |     |-- id_str : string
|     |-- urls (array)     
|-- extended_entities (struct)
|-- retweeted_status (struct)
|-- user (struct)
_

この構造を以下のように平坦化したいのですが、

期待される結果

_root
|-- contributors : string
|-- created_at : string
|-- entities (struct)
|-- entities.hashtags (array) : [string]
|-- entities.media (array)
|-- entities.media.additional_media_info (struct)
|-- entities.media.additional_media_info.description : string
|-- entities.media.additional_media_info.embeddable : boolean
|-- entities.media.additional_media_info.monetizable : bollean
|-- entities.media.diplay_url : string
|-- entities.media.id : long
|-- entities.media.id_str : string
|-- entities.urls (array)     
|-- extended_entities (struct)
|-- retweeted_status (struct)
|-- user (struct)
_

データベース移動先: データ-178 KB 。次に、番号の付いたアイテムを「example」という名前のテキストファイルにコピーします。作業ディレクトリに作成した「../example.json/」という名前のディレクトリに保存します。

Rコードは、以下の例を再現するように記述されています。

終了コード

_library(sparklyr)
library(dplyr)
library(devtools)
  devtools::install_github("mitre/sparklyr.nested")
# If Spark is not installed, then also need:
# spark_install(version = "2.2.0")
library(sparklyr.nested)
library(testthat)
library(jsonlite)

Sys.setenv(SPARK_HOME="/usr/lib/spark")    
conf <- spark_config()
conf$'sparklyr.Shell.executor-memory' <- "20g"
conf$'sparklyr.Shell.driver-memory' <- "20g"
conf$spark.executor.cores <- 16
conf$spark.executor.memory <- "20G"
conf$spark.yarn.am.cores  <- 16
conf$spark.yarn.am.memory <- "20G"
conf$spark.executor.instances <- 8
conf$spark.dynamicAllocation.enabled <- "false"
conf$maximizeResourceAllocation <- "true"
conf$spark.default.parallelism <- 32
sc <- spark_connect(master = "local", config = conf, version = '2.2.0') # Connection             
 sample_tbl <- spark_read_json(sc,name="example",path="example.json", header = TRUE, memory = FALSE, overwrite = TRUE) 
 sdf_schema_viewer(sample_tbl) # to create db schema
_

取られた努力

Jsonliteを使用しました。ただし、大きなファイルやチャンク内を読み取ることはできません。終わりのない時間がかかりました。それで、数秒以内に10億のレコードを不思議に思って読んだので、私はSparklyrに目を向けました。レコードを深いネスティングレベルまでフラット化するためのさらなる調査を行いました(フラット化はjsonliteパッケージでflatten()関数を使用して行われるため)。しかし、Sparklyrには、そのような機能はありません。 Sparklyrでは第1レベルの平坦化のみが可能でした。

さまざまなデータタイプのデータをフラット化し、CSVファイルで出力したい。

14
Shree

了解しました。これは、すべてを理解するための1つの可能な方法です。

スキーマ情報を使用して、ネストされたすべての名前を作成できます。例えば、 entities.media.additional_media_infoの場合、SQLを使用してそれらを選択できます。

これは少し労働集約的であり、一般化されないかもしれませんが、それは動作します

これもSELECTステートメントにすぎないので、これも迅速に行う必要があると思います。

columns_to_flatten <- sdf_schema_json(sample_tbl, simplify = T) %>%
  # using rlist package for ease of use
  rlist::list.flatten(use.names = T) %>%
  # get names
  names() %>%
  # remove contents of brackets and whitespace
  gsub("\\(.*?\\)|\\s", "", .) %>%
  # add alias for column names, dot replaced with double underscore
  # this avoids duplicate names that would otherwise occur with singular
  {paste(., "AS", gsub("\\.", "__", .))} %>%
  # required, otherwise doesn't seem to work
  sub("variants", "variants[0]", .)

# construct query
sql_statement <- paste("SELECT",
                       paste(columns_to_flatten, collapse = ", "),
                       "FROM example")

# execute on spark cluster, save as table in cluster
spark_session(sc) %>%
  sparklyr::invoke("sql", sql_statement) %>%
  sparklyr::invoke("createOrReplaceTempView", "flattened_example")

tbl(sc, "flattened_example") %>%
  sdf_schema_viewer()

enter image description here


生成されたSQLは次のようになりますが、かなり単純で、長いだけです。

SELECT contributors AS contributors, coordinates AS coordinates, created_at AS created_at, display_text_range AS display_text_range, entities.hashtags.indices AS entities__hashtags__indices, entities.hashtags.text AS entities__hashtags__text, entities.media.additional_media_info.description AS entities__media__additional_media_info__description, entities.media.additional_media_info.embeddable AS entities__media__additional_media_info__embeddable, entities.media.additional_media_info.monetizable AS entities__media__additional_media_info__monetizable, entities.media.additional_media_info.title AS entities__media__additional_media_info__title, entities.media.display_url AS entities__media__display_url, entities.media.expanded_url AS entities__media__expanded_url, entities.media.id AS entities__media__id, entities.media.id_str AS entities__media__id_str, entities.media.indices AS entities__media__indices, entities.media.media_url AS entities__media__media_url, entities.media.media_url_https AS entities__media__media_url_https, entities.media.sizes.large.h AS entities__media__sizes__large__h, entities.media.sizes.large.resize AS entities__media__sizes__large__resize, entities.media.sizes.large.w AS entities__media__sizes__large__w FROM example
9
zacdav