Извлечь значения столбца 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