[scala] Apache Spark에서 Dataframe의 열 값을 List로 추출

데이터 프레임의 문자열 열을 목록으로 변환하고 싶습니다. DataframeAPI 에서 찾을 수있는 것은 RDD이므로 먼저 RDD로 다시 변환 한 다음 toArrayRDD에 기능을 적용 해 보았습니다 . 이 경우 길이와 SQL이 잘 작동합니다. 그러나 RDD에서 얻은 결과에는 이와 같은 모든 요소 주위에 대괄호가 있습니다 [A00001]. 열을 목록으로 변환하는 적절한 방법이나 대괄호를 제거하는 방법이 있는지 궁금합니다.

모든 제안을 주시면 감사하겠습니다. 감사합니다!



답변

단일 목록을 포함하는 컬렉션을 반환해야합니다.

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

매핑이 없으면 데이터베이스의 모든 열을 포함하는 Row 개체 만 가져옵니다.

이것은 아마도 모든 유형의 목록을 얻을 것임을 명심하십시오. 결과 유형을 지정하려면 r => r(0).asInstanceOf[YOUR_TYPE]매핑에 .asInstanceOf [YOUR_TYPE]을 사용할 수 있습니다.

추신 자동 변환으로 인해 .rdd부분을 건너 뛸 수 있습니다 .


답변

Spark 2.x 및 Scala 2.11 사용

특정 열의 값을 List로 변환하는 세 가지 가능한 방법을 생각합니다.

모든 접근 방식에 대한 공통 코드 조각

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()하고 각 레코드에서 요소 0을 선택합니다.

이것은 훌륭한 방법이 될 수 없습니다. 다음 접근 방식으로 개선합시다.


접근 방식 2

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

어떻게 더 낫습니까? 단일 드라이버가 아닌 작업자간에 맵 변환로드를 분산했습니다.

I의 노하우는 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 노트북


답변

나는 주어진 대답이 Scala에 대해 가정된다는 것을 알고 있으므로 PySpark 사용자가 궁금한 경우를 대비하여 Python 코드의 작은 스 니펫을 제공하고 있습니다. 구문은 주어진 대답과 유사하지만 목록을 제대로 표시하려면 실제로 매핑 함수에서 열 이름을 두 번 참조해야하며 select 문이 필요하지 않습니다.

즉 “Raw”라는 열을 포함하는 DataFrame

각 항목이 “Raw”의 행 값인 목록으로 결합 된 “Raw”의 각 행 값을 얻으려면 다음을 사용합니다.

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


답변

Scala 및 Spark 2+에서 다음을 시도하십시오 (열 이름이 “s”라고 가정).
df.select('s).as[String].collect


답변

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()

여기에 수집은 차례로 목록으로 변환하는 함수입니다. 방대한 데이터 세트의 목록을 사용하십시오. 성능이 저하됩니다. 데이터를 확인하는 것이 좋습니다.


답변

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 (Real Programming Language)에 대한 해결책을 제시하지 않았기 때문에 나중에 감사 할 수 있습니다.