Извлечь значения столбца Dataframe в виде списка в Apache Spark

Я хотел бы преобразовать строковый столбец данных в список. Что я могу найти из Dataframe API является RDD, поэтому я попытался сначала преобразовать его в RDD, а затем применить toArray функция к СДР. В этом случае длина и SQL работают просто отлично. Тем не менее, результат, который я получил от RDD, имеет квадратные скобки вокруг каждого элемента, как это [A00001], Мне было интересно, если есть подходящий способ преобразовать столбец в список или способ убрать квадратные скобки.

Мы ценим любые предложения. Спасибо!

5 ответов

Решение

Это должно вернуть коллекцию, содержащую один список:

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

Без сопоставления вы просто получаете объект Row, который содержит каждый столбец из базы данных.

Имейте в виду, что это, вероятно, даст вам список любого типа. Если вы хотите указать тип результата, вы можете использовать.asInstanceOf[YOUR_TYPE] в r => r(0).asInstanceOf[YOUR_TYPE] отображение

PS из-за автоматического преобразования вы можете пропустить .rdd часть.

С 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 эффективны, наконец, третий - эффективный и элегантный (я думаю, что).

Ссылка на блокнот Databricks, которая будет доступна до 6 месяцев с 2017/05/20

Я знаю, что ответ, который был задан и запрошен, предполагается для Scala, поэтому я просто предоставляю небольшой фрагмент кода Python на случай, если пользователю PySpark будет любопытно. Синтаксис аналогичен приведенному ответу, но чтобы правильно вывести список из списка, мне нужно во второй раз ссылаться на имя столбца в функции отображения, и мне не нужен оператор выбора.

т.е. DataFrame, содержащий столбец с именем "Raw"

Чтобы получить каждое значение строки в "Raw", объединенное в список, где каждая запись является значением строки из "Raw", я просто использую:

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

В Scala и Spark 2+ попробуйте это (при условии, что имя вашего столбца "s"):df.select('s).as[String].collect

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(настоящий язык программирования), можете поблагодарить меня позже

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

это отлично работает

from pyspark.sql.functions import col

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

здесь collect - это функции, которые, в свою очередь, преобразуют его в список. Остерегайтесь использовать список на огромном наборе данных. Это снизит производительность. Хорошо бы проверить данные.

Ниже для Python-

df.select("col_name").rdd.flatMap(lambda x: x).collect()

Обновленное решение со списком:

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

Это ответ Java.

df.select("id").collectAsList();
Другие вопросы по тегам