簡體   English   中英

從另一個數據中的選定信息創建新數據框

[英]Create new dataframe from selected information from another datama

我有一個具有以下架構的數據框:

root
 |-- id: long (nullable = true)
 |-- type: string (nullable = true)
 |-- tags: map (nullable = true)
 |    |-- key: string
 |    |-- value: string (valueContainsNull = true)
 |-- lat: Long (nullable = true)
 |-- lon: Long (nullable = true)
 |-- nds: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- ref: long (nullable = true)
 |-- members: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- type: string (nullable = true)
 |    |    |-- ref: long (nullable = true)
 |    |    |-- role: string (nullable = true)

我想創建一個新的數據框res ,我在其中從列tags選擇特定數據。 我所需要的valueskey=placekey=population 新數據框應具有以下架構:

val schema = StructType(
               Array(
                 StructField("place", StringType),
                 StructField("population", LongType)
               )
             )

我完全不知道該怎么做。 我試圖復制第一個數據框,然后選擇列,但這沒有用。

有人有解決方案嗎?

讓我們調用您的原始數據框df 你可以像這樣提取你想要的信息

import org.apache.spark.sql.functions.sql.col

val data = df
  .select("tags")
  .where(
    df("tags")("key") isin (List("place", "population"): _*)
  )
  .select(
    col("tags")("value")
  )
  .collect()
  .toList

這將為您提供一個List[Row] ,它可以使用您的架構轉換為另一個數據框

import scala.collection.JavaConversions.seqAsJavaList

sparkSession.createDataFrame(seqAsJavaList[Row](data), schema)

給定以下簡化輸入:

val df = Seq(
  (1L, Map("place" -> "home", "population" -> "1", "name" -> "foo")),
  (2L, Map("place" -> "home", "population" -> "4", "name" -> "foo")),
  (3L, Map("population" -> "3")),
  (4L, Map.empty[String, String])
).toDF("id", "tags")

您想使用map_filter方法來選擇值以過濾映射以僅包含您想要的鍵,然后調用map_values來獲取這些條目。 map_values返回一個數組,因此您需要使用explode_outer來展平數據。 我們在這里使用explode_outer是因為您可能有既沒有地方也沒有人口的條目,或者只有兩者之一。 一旦數據形成我們可以輕松使用的表單,我們只需在所需結構中選擇我們想要的字段。

我保留了id列,因此當您運行示例時,您可以看到我們不會刪除缺少數據的條目。


val r = df.select(
    col("id"),
    explode_outer(map_values(map_filter(col("tags"), (k,_) => k === "place"))) as "place",
    map_values(map_filter(col("tags"), (k,_) => k === "population")) as "population"
  ).withColumn("population", explode_outer(col("population")))
  .select(
    col("id"),
    array(
      struct(
        col("place"),
        col("population") cast LongType as "population"
      ) as "place_and_population"
    ) as "data"
  )

給出:

root
 |-- id: long (nullable = false)
 |-- data: array (nullable = false)
 |    |-- element: struct (containsNull = false)
 |    |    |-- place: string (nullable = true)
 |    |    |-- population: long (nullable = true)

+---+--------------+
| id|          data|
+---+--------------+
|  1|   [{home, 1}]|
|  2|   [{home, 4}]|
|  3|   [{null, 3}]|
|  4|[{null, null}]|
+---+--------------+

您可以直接在類型映射的列上應用所需的鍵來提取值,然后按您的意願強制轉換和重命名列,如下所示:

import org.apache.spark.sql.functions.col
import org.apache.spark.sql.types.LongType

val result = dataframe.select(
  col("tags")("place").as("place"),
  col("tags")("population").cast(LongType).as("population")
)

帶有以下tags列:

+------------------------------------------------+
|tags                                            |
+------------------------------------------------+
|{place -> A, population -> 32, another_key -> X}|
|{place -> B, population -> 64, another_key -> Y}|
+------------------------------------------------+

你得到以下結果:

+-----+----------+
|place|population|
+-----+----------+
|A    |32        |
|B    |64        |
+-----+----------+

具有以下架構:

root
 |-- place: string (nullable = true)
 |-- population: long (nullable = true)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM