[英]Joining dataframes without ON clause but with multiple column condition and populate flag in pyspark
我正在嘗試通過與某些列條件匹配來加入 2 個數據框並從 A 中檢索 ID。 基本上我必須用來自 A 的 ID 填充 B 中的 '0' 並且我沒有為此的 ON 子句,所以我可能需要交叉連接,但問題是我只需要設置 B。
下面是我用 pyspark 寫的測試數據
import sys
from pyspark.sql.functions import lit, count, col, when
from pyspark.sql.window import Window
# Create the two dataframes
B = sqlContext.createDataFrame([(0,'Sam',100,'ind','IT','2/11/2019'),
(0,'Tom',2000,'usa','HR','2/11/2019'),
(0,'Kom',3500,'uk','IT','2/11/2019'),
(0,'Nom',4000,'can','HR','2/11/2019'),
(0,'Vom',5000,'mex','IT','2/11/2019'),
(0,'XYZ',5000,'mex','IT','2/11/2019')],
['ID','AName','ASal','BAddress','CDept','DJoin_Date'])
A = sqlContext.createDataFrame([(11,'Sam',100,'ind','ITA','2/11/2019'),(22,'Tom',2000,'usa','HRA','2/11/2019'),
(33,'Kom',3000,'uuk','ITA','2/11/2019'),(44,'Nom',4000,'can','HRA','2/11/2019'),
(55,'Xum',5000,'mex','ITA','2/11/2019'),(77,'XYZ',5000,'mex','ITA','2/11/2019')],
['ID','AName','ASal','BAddress','CDept','DJoin_Date'])
A.show()
B.show()
預期 output 是
ID,AName,ASal,BAddress,CDept,DJoin_Date,indicator
11,Sam,100,ind,IT,2/11/2019,case1 and case2
22,Tom,2000,usa,HR,2/11/2019,case1 and case2
33,Kom,3500,uk,IT,2/11/2019,case1
44,Nom,4000,can,HR,2/11/2019,case1 and case2
0,Vom,5000,mex,IT,2/11/2019,
77,XYZ,5000,mex,IT,2/11/2019,case1 and case2
最好的方法是什么。對於條件檢查,我嘗試在 withColumn 中使用 udf,但我還需要返回 2 個值(ID 和指標)。 所以我認為 udf 在這種情況下不起作用
更新 1
另一個疑問與同一個問題有關。 我不想為此創建另一個線程。 所以在這里問。
假設我在兩個 df 中還有一列,即 ID、AName、ASal、BAddress、CDept、DJoin_Date、ID2
如果 Name 和 sal 匹配,B.ID 應該包含 A.ID 的值,但是如果地址匹配而不是用 A.ID 替換 B.ID,我需要用 B.ID2 = A.ID2 替換它們
我能在同一個 select 查詢中做到這一點嗎? 通過獲取指標標志值? 例如,如果指標 == 案例 1 和案例 2,則替換 B.ID2=A.ID2。 但是 select 語句中的新指標列是否可用於進行條件檢查(因為指標列不是 A 或 B 數據幀的一部分)?
更新 2
對數據集進行了一些更改
import sys
from pyspark.sql.functions import lit, count, col, when
from pyspark.sql.window import Window
# Create the two dataframes
B = sqlContext.createDataFrame([(0,'Sam',100,'ind','IT',0),
(0,'Tom',2000,'usa','HR',30),
(0,'Kom',3500,'uk','IT',-8),
(0,'XYZ',5000,'mex','IT',25)],
['ID','AName','ASal','BAddress','CDept','ID2'])
A = sqlContext.createDataFrame([(11,'Sam',100,'Korea','ITA',500),(22,'Jack',2000,'usa','HRA',4500),
(33,'Kom',3500,'uk','ITA',5009)],
['ID','AName','ASal','BAddress','CDept','ID2'])
df = B.join(A, ['AName', 'ASal'], 'left').select(
F.coalesce(A.ID, B.ID).alias('ID'),
'AName',
'ASal',
B.BAddress,
B.CDept,
F.when(
A.ID.isNull() & (B.BAddress == A.BAddress),
'case2'
).when(
A.ID.isNotNull() & (B.BAddress == A.BAddress),
'case1 and case2'
).when(
A.ID.isNotNull(),
'case1'
).alias('indicator'),
F.when(
A.ID.isNotNull() & (B.BAddress == A.BAddress),
A.ID2
).otherwise(B.ID2).alias('ID2')
)
Output
+---+-----+----+--------+-----+---------------+----+
| ID|AName|ASal|BAddress|CDept| indicator| ID2|
+---+-----+----+--------+-----+---------------+----+
| 33| Kom|3500| uk| IT|case1 and case2|5009|
| 11| Sam| 100| ind| IT| case1| 0|
| 0| XYZ|5000| mex| IT| null| 25|
| 0| Tom|2000| usa| HR| null| 30|
+---+-----+----+--------+-----+---------------+----+
預期 output
+---+-----+----+--------+-----+---------------+----+
| ID|AName|ASal|BAddress|CDept| indicator| ID2|
+---+-----+----+--------+-----+---------------+----+
| 33| Kom|3500| uk| IT|case1 and case2|5009|
| 11| Sam| 100| ind| IT| case1| 0|
| 0| XYZ|5000| mex| IT| null| 25|
| 0| Tom|2000| usa| HR| **case2| 4500**|
+---+-----+----+--------+-----+---------------+----+
3.if(B.BAddress= A.BAddress) 然后我需要獲取 A.ID2 並將它們放入 B.ID2 並生成一個值為“case2”的指標列 4. if(B.AName= A.Aname and B .ASal= A.ASal ) 和 (B.BAddress= A.BAddress ) 然后我需要獲取 ID 並將它們放入 B.ID 並生成一個值為“case1 和 case2”的指示符列
我正在努力達到第三點。 但它正在返回 null
您可以對 AName 和 ASal 進行左連接,並使用when
檢查 A.ID 是否為 null 的指示符(這表明 AName 和 ASal 上沒有匹配項)。 如果不是null,則表示有匹配,則可以分配地址是否匹配的指標。
import pyspark.sql.functions as F
df = B.join(A, ['AName', 'ASal'], 'left').select(
F.coalesce(A.ID, B.ID).alias('ID'),
'AName',
'ASal',
B.BAddress,
B.CDept,
B.DJoin_Date,
F.when(
A.ID.isNotNull() & (B.BAddress == A.BAddress),
'case1 and case2'
).when(
A.ID.isNotNull(),
'case1'
).alias('indicator')
).orderBy('ID')
df.show()
+---+-----+----+--------+-----+----------+---------------+
| ID|AName|ASal|BAddress|CDept|DJoin_Date| indicator|
+---+-----+----+--------+-----+----------+---------------+
| 0| Vom|5000| mex| IT| 2/11/2019| null|
| 11| Sam| 100| ind| IT| 2/11/2019|case1 and case2|
| 22| Tom|2000| usa| HR| 2/11/2019|case1 and case2|
| 33| Kom|3500| uk| IT| 2/11/2019| case1|
| 44| Nom|4000| can| HR| 2/11/2019|case1 and case2|
| 77| XYZ|5000| mex| IT| 2/11/2019|case1 and case2|
+---+-----+----+--------+-----+----------+---------------+
如果您還有一個 ID2 列,您可以執行類似的操作
df = B.join(A, ['AName', 'ASal'], 'left').select(
F.coalesce(A.ID, B.ID).alias('ID'),
'AName',
'ASal',
B.BAddress,
B.CDept,
B.DJoin_Date,
F.when(
A.ID.isNotNull() & (B.BAddress == A.BAddress),
'case1 and case2'
).when(
A.ID.isNotNull(),
'case1'
).alias('indicator'),
F.when(
A.ID.isNotNull() & (B.BAddress == A.BAddress),
B.ID2
).otherwise(A.ID2)
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.