0

많은 열이있는 스파크 데이터 프레임이 있습니다. 이제 저는 그것들을지도에 결합하고 새로운 열을 만들고 싶습니다. 예 :스파크 데이터 프레임 열을 맵 열에 포함시키는 방법은 무엇입니까?

df.withColumn("newcol", struct(df.columns.head, df.columns.tail: _*)) 

그러나, 나는 여전히 dataset df 명령 변환해야합니다 :이 작업을 수행하는

col1:String col2:String col3:String... coln:String => 
col: Map(colname -> colval) 

한 가지 방법이다. 나는 struct 타입과 일치 할 수있는 케이스 클래스를 정의하는 방법을 모른다.

또 다른 옵션은지도 유형에 항목을 삽입하는 것이지만이를 표현하는 방법을 모르겠습니다.

+0

데이터 프레임에 몇 행이 있습니까? –

+0

약 40이고, 하나씩 나열하는 것은 지루합니다. – user3162587

+1

나는 그 질문을 이해하지 못합니다. 'Map (colname -> colval)''colval'은'colname'에있는 모든 값의 배열이어야합니까? 그리고 여러분이 제공 한 방법은 각 행을 구조체로 가져옵니다. 위에 설명 된 내용과 정확히 일치하지는 않습니다. 샘플 데이터 세트와 필요한 출력을 자세히 설명해 주실 수 있습니까? – philantrovert

답변

1

기존의 모든 열에서 새 열을 작성하려면 다음과 같은 간단한 해결책이 있습니다.

var mydata = Seq(("a", "b", "c"), ("d", "e", "f"), ("g", "h", "i")) 
       .toDF("f1", "f2", "f3") 

var colnms = mydata.columns.map(lit(_)) 
var colvals = mydata.columns.map(col(_)) 
var colnms_n_vals = colnms.zip(colvals).flatMap{ case (a,b) => Array(a,b) } 

display(mydata.withColumn("myMap", map(colnms_n_vals:_*))) 

결과 :

여기
org.apache.spark.sql.functions.map 

가 완벽하게 작동 예입니다

import org.apache.spark.sql.functions._ 
val columnsName = ds.columns 
val mkMap = udf((values: mutable.WrappedArray[Int]) => columnsName.zip(values).toMap) 
ds.withColumn("new_col", mkMap(array(columnsName.head, columnsName.tail:_*))) 
1

는 성능상의 이유로, 당신은 기존 스파크 기능을 사용하여 자신의 UDF 롤링 방지 할 수 있습니다 이 :

f1 f2 f3 myMap 
a b c {"f1":"a","f2":"b","f3":"c"} 
d e f {"f1":"d","f2":"e","f3":"f"} 
g h i {"f1":"g","f2":"h","f3":"i"} 
+0

(Spark API 문서에 따라)이 작업을 수행하려면 모든 열에 동일한 데이터 유형이 필요하다는 점에 유의해야합니다. – Chondrops