Витяг значень стовпців Dataframe як списку в Apache Spark


86

Я хочу перетворити рядок стовпця кадру даних у список. Що я можу знайти в DataframeAPI, це RDD, тому я спробував перетворити його назад у RDD, а потім застосувати toArrayфункцію до RDD. У цьому випадку довжина та SQL працюють нормально. Однак результат, який я отримав від RDD, має квадратні дужки навколо кожного такого елемента [A00001]. Мені цікаво, чи є відповідний спосіб перетворити стовпець у список або спосіб видалити квадратні дужки.

Будь-які пропозиції будуть вдячні. Дякую!


Відповіді:


116

Це повинно повернути колекцію, що містить єдиний список:

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()

Без зіставлення ви просто отримуєте об'єкт "Рядок", який містить кожен стовпець з бази даних.

Майте на увазі, що це, ймовірно, дасть вам список будь-якого типу. ÏЯкщо ви хочете вказати тип результату, ви можете використовувати .asInstanceOf [YOUR_TYPE] у r => r(0).asInstanceOf[YOUR_TYPE]відображенні

PS завдяки автоматичному перетворенню ви можете пропустити .rddчастину.


3
З якихось дивних причин це працює навпаки (Spark 2.1.0) collect().map(r => r(0))- чи є у цього замовлення якісь недоліки?
Боерн

Може бути повільнішим - ваше рішення спочатку збирає всі дані на драйвері, а після цього виконує відображення на драйвері (без допомоги виконавців), використовуючи лише обробну потужність одного драйвера.
Німанд

72

З Spark 2.x та Scala 2.11

Я б подумав про 3 можливі способи перетворення значень конкретного стовпця в Список.

Загальні фрагменти коду для всіх підходів

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.getOrCreate    
import spark.implicits._ // for .toDF() method

val df = Seq(
    ("first", 2.0),
    ("test", 1.5), 
    ("choose", 8.0)
  ).toDF("id", "val")

Підхід 1

df.select("id").collect().map(_(0)).toList
// res9: List[Any] = List(one, two, three)

Що відбувається зараз? Ми збираємо дані Драйверу з collect()і вибираємо нульовий елемент з кожного запису.

Це не може бути чудовим способом зробити це. Давайте вдосконалимо його наступним підходом.


Підхід 2

df.select("id").rdd.map(r => r(0)).collect.toList 
//res10: List[Any] = List(one, two, three)

Як це краще? Ми розподілили навантаження на перетворення карти серед робітників, а не одного драйвера.

Я знаю, rdd.map(r => r(0))це не здається вам елегантним. Отже, давайте розглянемо це в наступному підході.


Підхід 3

df.select("id").map(r => r.getString(0)).collect.toList 
//res11: List[String] = List(one, two, three)

Тут ми не перетворюємо DataFrame на RDD. Подивіться, mapвін не прийме r => r(0)(або _(0)) як попередній підхід через проблеми з кодером у DataFrame. Тож у кінцевому підсумку використовуйте, r => r.getString(0)і це буде розглянуто в наступних версіях Spark.

Висновок

Усі варіанти дають однакові результати, але ефективні 2 і 3, нарешті 3-й - ефективний і елегантний (я думаю).

Databricks ноутбук


24

Я знаю, що для Scala передбачається відповідь, яку дають і просять, тому я просто надаю невеликий фрагмент коду Python на випадок, якщо користувачеві PySpark буде цікаво. Синтаксис схожий на дану відповідь, але для правильного виведення списку я насправді маю вдруге посилатися на назву стовпця у функції зіставлення, і мені не потрібен оператор select.

тобто DataFrame, що містить стовпець "Raw"

Щоб отримати кожне значення рядка в "Raw", об'єднане у вигляді списку, де кожен запис є значенням рядка з "Raw", я просто використовую:

MyDataFrame.rdd.map(lambda x: x.Raw).collect()

4
Це дає список об'єктів рядка. Що робити, якщо вам потрібен список значень?
ThatDataGuy

Це дає список значень.
Еббі Собх

Дякуємо, що поділилися цим! Це для мене чудово працює, просто цікаво, чи є спосіб пришвидшити це, він працює досить повільно
Мойган Мазучі

5

У Scala та Spark 2+ спробуйте наступне (за умови, що назва стовпця "s"): df.select('s).as[String].collect


3
sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets

це працює чудово


1
List<String> whatever_list = df.toJavaRDD().map(new Function<Row, String>() {
    public String call(Row row) {
        return row.getAs("column_name").toString();
    }
}).collect();

logger.info(String.format("list is %s",whatever_list)); //verification

Оскільки ніхто не дав жодного рішення в java (справжня мова програмування), я можу подякувати мені пізніше


0
from pyspark.sql.functions import col

df.select(col("column_name")).collect()

тут збір - це функції, які в свою чергу перетворюють його в список. Будьте готові використовувати список із величезного набору даних. Це зменшить продуктивність. Добре перевірити дані.



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.