Извлечение значений столбцов Dataframe в виде списка в Apache Spark
Я хочу преобразовать строковый столбец фрейма данных в список. В API Dataframe
я могу найти RDD, поэтому я попытался сначала преобразовать его в RDD, а затем применить функцию toArray
к RDD. В этом случае длина и SQL работают просто отлично. Тем не менее, результат, который я получил от RDD, имеет квадратные скобки вокруг каждого элемента, подобного этому [A00001]
. Мне было интересно, есть ли подходящий способ преобразования столбца в список или способ удаления квадратных скобок.
Мы ценим любые предложения. Спасибо!
Ответы
Ответ 1
Это должно вернуть коллекцию, содержащую один список:
dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()
Без отображения вы просто получаете объект Row, содержащий каждый столбец из базы данных.
Имейте в виду, что это, вероятно, даст вам список любого типа. Если вы хотите указать тип результата, вы можете использовать .asInstanceOf [YOUR_TYPE] в r => r(0).asInstanceOf[YOUR_TYPE]
mapping
P.S. из-за автоматического преобразования вы можете пропустить часть .rdd
.
Ответ 2
С 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)
Что происходит сейчас? Мы собираем данные для Driver с 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)
и это будет r => r.getString(0)
в следующих версиях Spark.
Заключение
Все опции дают одинаковый результат, но 2 и 3 эффективны, наконец, третий - эффективный и элегантный (я думаю, что).
Ссылка на блокнот Databricks, которая будет доступна до 6 месяцев с 2017/05/20
Ответ 3
Я знаю, что ответ, указанный и запрошенный, предполагается для Scala, поэтому я просто предоставляю небольшой фрагмент кода Python, если пользователю PySpark интересно. Синтаксис подобен данному ответу, но для правильного отображения списка я действительно должен ссылаться на имя столбца второй раз в функции сопоставления, и мне не нужен оператор select.
то есть. DataFrame, содержащий столбец с именем "Raw"
Чтобы получить каждое значение строки в "Raw" , объединенное как список, где каждая запись представляет собой значение строки из "Raw" , я просто использую:
MyDataFrame.rdd.map(lambda x: x.Raw).collect()
Ответ 4
В Scala и Spark 2+ попробуйте это (при условии, что ваше имя столбца "s" ):
df.select('s).as[String].collect
Ответ 5
sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets
работает отлично