2

でシンプルな行にデータフレームの複雑な行を分割:は、私はこのコードを持っているPyspark

from pyspark import SparkContext 
from pyspark.sql import SQLContext, Row 

sc = SparkContext() 
sqlContext = SQLContext(sc) 
documents = sqlContext.createDataFrame([ 
    Row(id=1, title=[Row(value=u'cars', max_dist=1000)]), 
    Row(id=2, title=[Row(value=u'horse bus',max_dist=50), Row(value=u'normal bus',max_dist=100)]), 
    Row(id=3, title=[Row(value=u'Airplane', max_dist=5000)]), 
    Row(id=4, title=[Row(value=u'Bicycles', max_dist=20),Row(value=u'Motorbikes', max_dist=80)]), 
    Row(id=5, title=[Row(value=u'Trams', max_dist=15)])]) 

documents.show(truncate=False) 
#+---+----------------------------------+ 
#|id |title        | 
#+---+----------------------------------+ 
#|1 |[[1000,cars]]      | 
#|2 |[[50,horse bus], [100,normal bus]]| 
#|3 |[[5000,Airplane]]     | 
#|4 |[[20,Bicycles], [80,Motorbikes]] | 
#|5 |[[15,Trams]]      | 
#+---+----------------------------------+ 

「ID」を保持したまま、私は得るために、複数の行に、すべての化合物の行(例えば2 & 4)を分割する必要があります次のような結果が得られます。

#+---+----------------------------------+ 
#|id |title        | 
#+---+----------------------------------+ 
#|1 |[1000,cars]      | 
#|2 |[50,horse bus]     | 
#|2 |[100,normal bus]     | 
#|3 |[5000,Airplane]     | 
#|4 |[20,Bicycles]      | 
#|4 |[80,Motorbikes]     | 
#|5 |[15,Trams]      | 
#+---+----------------------------------+ 
+0

私が構築していたアイデアです。「タイトル」カテゴリの各要素にIDを取得し(たとえば、各複合行に 'value'、' max_dist'、 'id'を含むようにして)、' flatMap'を実行します。 'map'は入力と出力の間に1対1の関係があるので、' map'を使用することはできません。私は時間があれば、後で答えを出すでしょう! –

+0

ありがとう@Katyaハンドラー、私はあなたのアイデアを試してみます。もし私ができなかったら、私はあなたの助けを借りてコメントします:-) –

答えて

11

だけexplodeそれ:私は(!申し訳ありません)が、ここで答えを書く時間がない

from pyspark.sql.functions import explode 

documents.withColumn("title", explode("title")) 
## +---+----------------+ 
## | id|   title| 
## +---+----------------+ 
## | 1|  [1000,cars]| 
## | 2| [50,horse bus]| 
## | 2|[100,normal bus]| 
## | 3| [5000,Airplane]| 
## | 4| [20,Bicycles]| 
## | 4| [80,Motorbikes]| 
## | 5|  [15,Trams]| 
## +---+----------------+ 
+1

これははるかに良い答えです@ K.Ali –

+0

いつものように@ zero323、ありがとうございます。 –

+0

もう一度質問@ zero323してください、それも爆発することができますか? struct(col_1 = 1000、col_2 = 'cars'など)のフィールドによって垂直方向に結果の列 'title'が表示されますか? –

1

これは私が思いついたものです。残念ながら、私はオブジェクトの世界を離れることがありました。listオブジェクトの世界に入る必要がありました。オブジェクトへの道を見つけることができなかったので、appendです。

つまり、このメソッドはちょっと混乱しています。 オブジェクトに新しい列を追加する方法が見つかった場合は、これは方法ではありません。私はdf.show()を実行すると

def add_id(row): 
    it_list = [] 
    for i in range(0, len(row[1])): 
     sm_list = [] 
     for j in row[1][i]: 
      sm_list.append(j) 
     sm_list.append(row[0]) 
     it_list.append(sm_list) 
    return it_list 

with_id = documents.flatMap(lambda x: add_id(x)) 

df = with_id.map(lambda x: Row(id=x[2], title=Row(value=x[0], max_dist=x[1]))).toDF() 

、私が取得:

+---+----------------+ 
| id|   title| 
+---+----------------+ 
| 1|  [cars,1000]| 
| 2| [horse bus,50]| 
| 2|[normal bus,100]| 
| 3| [Airplane,5000]| 
| 4| [Bicycles,20]| 
| 4| [Motorbikes,80]| 
| 5|  [Trams,15]| 
+---+----------------+ 
+0

私が提案するかもしれない: 'def flatten(row):id_、items = row; ( '' id ''、 'title' ') ''の後ろに '' item.ldd.flatMap(flatten).toDF'が続きます。 – zero323

+0

もう一度@Katya Handlerさん、ありがとうございました:-) –

関連する問題