[英]How can I do conditional joins in python like subquery?
我有 2 個 df。
我想獲取 df2 的類別,但沒有公共鍵。
df1 的代碼應該在 range1 和 range2 之間。
df2 的 s_date 只有 2 個值(20210101、20220101)
df1
代碼 | 日期 |
---|---|
A51 | 20221215 |
C52 | 20221215 |
A51 | 20211215 |
D89 | 20211215 |
df2
范圍 1 | 范圍2 | s_date | 類別 |
---|---|---|---|
A00 | B99 | 20220101 | 一種 |
C50 | C60 | 20220101 | 乙 |
A00 | B60 | 20210101 | AA |
D00 | D90 | 20210101 | DD |
對於輸出,我使用如下語句的 SQL 完成了這項工作,
但我想用 python(pandas) 來完成這項工作。
輸出
代碼 | 日期 | 類別 |
---|---|---|
A51 | 20221215 | 一種 |
C52 | 20221215 | 乙 |
A51 | 20211215 | AA |
D89 | 20211215 | DD |
SELECT
code, date,
CASE WHEN date >= '20220101'
THEN (SELECT category
FROM df2
WHERE code BETWEEN range1 AND range2
AND s_date = '20220101'
ELSE (SELECT category
FROM df2
WHERE code BETWEEN range1 AND range2
AND s_date = '20210101') END AS category
FROM df1
謝謝。
您可以直接在 python 中比較字符串。 例如,'A50' > 'A00' 將返回True ,而 'A50' > 'B00' 將返回False 。 我們可以使用它按此值過濾 df2。
這是它可能在代碼中看到的奶牛:
categories = []
for row in df1.values:
code = row['code']
date = row['date']
if date >= '20220101':
category = df2[(df2['range1'] < code) & (code < df2['range2']) & (df2['s_date'] == '20220101')]['category']
else:
category = df2[(df2['range1'] < code) & (code < df2['range2']) & (df2['s_date'] == '20210101')]['category']
categories.append(category)
df1['category'] = categories
也許有更優雅的方法,但主要模式就是這樣。
date
和code
對行進行排序。 一種方法是定義這些列的整數編碼,然后使用merge_asof組合數據幀。
我們將定義一個編碼函數,假設code
保證是三個 ascii 字符(見注釋)。
from struct import pack, unpack
def encode(row, code_label='code', date_label='date'):
date_is_ge_20220101 = row[date_label] >= '20220101'
code_as_bytes = bytes(row[code_label], encoding='ascii')
return unpack('>I', pack('?3s', date_is_ge_20220101, code_as_bytes))[0]
執行編碼...
df1['encoding'] = df1.apply(encode, axis='columns')
df2['encoding'] = df2.apply(encode, axis='columns',
code_label='range1',
date_label='s_date')
合並時請記住merge_asof
需要對合並值進行排序。
pd.merge_asof(df1.sort_values('encoding'),
df2.sort_values('encoding'),
on='encoding')
給...
code date encoding range1 range2 s_date category
0 A51 20211215 4273457 A00 B60 20210101 AA
1 D89 20211215 4470841 D00 D90 20210101 DD
2 A51 20221215 21050673 A00 B99 20220101 A
3 C52 20221215 21181746 C50 C60 20220101 B
鄭重聲明,只有在絕對必要的情況下才能滿足項目的要求,我才會采用這種方法。 它與最初的問題陳述相去甚遠,盡管很有趣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.