2017-04-16 44 views
1

我已經試過無數方法把以下內容:如何按性別進行分組並按每組的位置加入?

Gender, Age, Value 
1,  20, 21 
2,  23 22 
1,  26, 23 
2,  29, 24 

Male_Age, Male_Value, Female_Age, Female_Value 
    20   21   23   22 
    26   23   29   24 

什麼,我需要做的是通過性別組,而不是使用總喜歡(求和,計數,AVG)我需要創建List [age]和List [value]。這應該是可能的,因爲我正在使用允許功能操作的數據集。

如果男性和女性的行數不相同,則列應填寫nulls

一種方法我試過是讓使用其他dataframes的列像這樣一個新的一個新的數據幀。male.select

DF 。選擇((「性」),其中('性別= == 1).COL( 「性別」),
female.select( 「性別」)。其中,('性=== 2).COL( 「性別」))

然而,這種奇怪產生像這樣的輸出:

sex, sex, 
1,  1 
2,  2 
1,  1 
2,  2 

我看不出這是怎麼可能的。

我也嘗試過使用支點,但它迫使我在group by後彙總:

df.withColumn( 「sex2」,df.col( 「性」))
.groupBy(」性 「)
.pivot(」 sex2 「) .agg( 總和( '值')。如(」 平均「),
STDDEV('值)。如( 」STD。dev的「)) 。 show()

|sex| 1.0_mean| 1.0_std. dev| 2.0_mean| 2.0_std. dev| 
|1.0|0.4926065526| 1.8110632697|   |    | 
|2.0|   |    |0.951250372|1.75060275400785| 

下面的代碼做什麼,我需要的Oracle SQL,因此它應該可以在星火SQL太我想...

drop table mytable 

CREATE TABLE mytable 
(gender number(10) NOT NULL, 
    age number(10) NOT NULL, 
    value number(10)); 

insert into mytable values (1,20,21); 
insert into mytable values(2,23,22); 
insert into mytable values (1,26,23); 
insert into mytable values (2,29,24); 
insert into mytable values (1,30,25); 

select * from mytable; 


SELECT A.VALUE AS MALE, 
     B.VALUE AS FEMALE 
FROM 
(select value, rownum RN from mytable where gender = 1) A 
FULL OUTER JOIN 
(select value, rownum RN from mytable where gender = 2) B 
ON A.RN = B.RN 

enter image description here

回答

0

以下應該會給你結果。

val df = Seq(
    (1,  20, 21), 
    (2,  23, 22), 
    (1,  26, 23), 
    (2,  29, 24) 
).toDF("Gender", "Age", "Value") 

scala> df.show 
+------+---+-----+ 
|Gender|Age|Value| 
+------+---+-----+ 
|  1| 20| 21| 
|  2| 23| 22| 
|  1| 26| 23| 
|  2| 29| 24| 
+------+---+-----+ 

// Gender 1 = Male 
// Gender 2 = Female 

import org.apache.spark.sql.expressions.Window 
val byGender = Window.partitionBy("gender").orderBy("gender") 

val males = df 
    .filter("gender = 1") 
    .select($"age" as "male_age", 
      $"value" as "male_value", 
      row_number() over byGender as "RN") 

scala> males.show 
+--------+----------+---+ 
|male_age|male_value| RN| 
+--------+----------+---+ 
|  20|  21| 1| 
|  26|  23| 2| 
+--------+----------+---+ 

val females = df 
    .filter("gender = 2") 
    .select($"age" as "female_age", 
      $"value" as "female_value", 
      row_number() over byGender as "RN") 

scala> females.show 
+----------+------------+---+ 
|female_age|female_value| RN| 
+----------+------------+---+ 
|  23|   22| 1| 
|  29|   24| 2| 
+----------+------------+---+ 

scala> males.join(females, Seq("RN"), "outer").show 
+---+--------+----------+----------+------------+ 
| RN|male_age|male_value|female_age|female_value| 
+---+--------+----------+----------+------------+ 
| 1|  20|  21|  23|   22| 
| 2|  26|  23|  29|   24| 
+---+--------+----------+----------+------------+ 
0

給出一個DataFrame稱爲df的列gender,agevalue,你可以這樣做:

df.groupBy($"gender") 
    .agg(collect_list($"age"), collect_list($"value")).rdd.map { row => 
    val ages: Seq[Int] = row.getSeq(1) 
    val values: Seq[Int] = row.getSeq(2) 
    (row.getInt(0), ages.head, ages.last, values.head, values.last) 
    }.toDF("gender", "male_age", "female_age", "male_value", "female_value") 

這使用非常有用的Spark functionslibrary中的collect_list聚合函數來聚合所需的值。 (正如你所看到的,也有collect_set爲好。)

在那之後,我不知道任何更高級別的DataFrame功能拓展這些柱狀陣列到自己的單獨列,所以我回落到我們的祖先使用的低級RDD API。我只需將所有內容都擴展爲Tuple,然後將其重新轉換爲DataFrame。上面的評論者提到了我沒有提到的角落案例;使用像headOptiontailOption這樣的函數可能會有用。但這應該足以讓你感動。

+0

這是非常不錯的維迪亞 - 更接近我需要的一步。但是,如何將這些列表轉換爲列的最後一步呢? – COOLBEANS

+0

函數'collect_list'和'as'返回'Column's。在我寫的內容中,年齡列表位於「年齡」列中,「值」列表位於「值」列中;都是'Column'對象。我不知道如何讓它們比'Column'-y更好。 – Vidya

+0

我明白了你的觀點,但我希望列表中的每個值都位於該列中的自己的行中。 – COOLBEANS

相關問題