問題
我需要撰寫一些 python 代碼來擴充visit_df表,以適應customer_df表中的日期范圍。本質上,該程式需要收集在日期范圍內(在 customer_df 表中的 START_DTM 和 END_DTM 之間)具有 VISIT_DTM 的給定客戶的每次訪問,然后生成一個結果表,其中屬性被收集到每個行的新單元格中訪問_df。
我確實有一個解決方案,但由于資料集很大,并且代碼嵌套 for 回圈效率低下,因此速度非常慢。請參閱下面的代碼。我懷疑有一些 Python/Pandas/numpy 函式的組合可能會更快更容易理解。
有沒有更好的方法來解決這個問題?
以下是輸入表:
訪問_df
|CUST_ID|VISIT_ID|VISIT_DTM|
|-------|--------|----------|
|1|1|2009-08-28 00:00:00.000000|
|1|2|2009-08-31 00:00:00.000000|
|20|11|2009-08-27 00:00:00.000000|
|20|21|2009-08-31 00:00:00.000000|
客戶_df
|CUST_ID|ATTR|START_DTM|END_DTM|
|-------|-------|------|------|
|1|'RED'|2008-08-27 00:00:00.000000|2008-08-28 00:00:00.000000|
|1|'BLUE'|2008-08-28 00:00:00.000000|2010-08-28 00:00:00.000000|
|1|'BLACK'|2009-08-29 00:00:00.000000|2010-08-28 00:00:00.000000|
|20|'YELLOW'|2008-08-26 00:00:00.000000|2009-08-28 00:00:00.000000|
|20|'BLUE'|2008-08-28 00:00:00.000000|2010-08-28 00:00:00.000000|
|20|BLACK|2009-08-29 00:00:00.000000|2010-09-03 00:00:00.000000|
這是想要的結果
結果在慢速代碼中命名為增強的visit_df
|CUST_ID|VISIT_ID|VISIT_DTM|ATTR_STR|ATTR_ARRAY|
|-------|--------|----------|-------|----------|
|1|1|2009-08-28 00:00:00.000000|'BLUE'|['BLUE']|
|1|2|2009-08-31 00:00:00.000000|'BLUE-BLACK'|['BLUE',BLACK']|
|20|11|2009-08-27 00:00:00.000000|'YELLOW-BLUE'|['YELLOW','BLUE']
|20|21|2009-08-31 00:00:00.000000|'BLUE-BLACK'|['BLUE','BLACK']
很慢的代碼
# Import pandas library
import pandas as pd
# Data
visit_data = [[1, 1, '2009-08-28 00:00:00.000000'],
[1, 2, '2009-08-31 00:00:00.000000'],
[20, 11, '2009-08-27 00:00:00.000000'],
[20, 21, '2009-08-31 00:00:00.000000']]
customer_attr = [[1,'RED', '2008-08-27 00:00:00.000000','2008-08-28 00:00:00.000000'],
[1,'BLUE', '2008-08-28 00:00:00.000000','2010-08-28 00:00:00.000000'],
[1, 'BLACK', '2009-08-29 00:00:00.000000', '2010-08-28 00:00:00.000000'],
[20,'YELLOW', '2008-08-26 00:00:00.000000','2009-08-28 00:00:00.000000'],
[20,'BLUE', '2008-08-28 00:00:00.000000','2010-08-28 00:00:00.000000'],
[20, 'BLACK', '2009-08-29 00:00:00.000000', '2010-09-03 00:00:00.000000'],
]
# Create the pandas DataFrames
visit_df = pd.DataFrame(visit_data, columns=['CUST_ID', 'VISIT_ID', 'VISIT_DTM'])
customer_df = pd.DataFrame(customer_attr, columns=['CUST_ID', 'ATTR', 'START_DTM', 'END_DTM'])
# Very slow code to augment the visit_df to produce a result df
visit_df['ATTR_STR'] = ''
visit_df['ATTR_ARRAY'] = ''
for index, visit_row in visit_df.iterrows():
attr_array = []
for index2, cust_row in customer_df.iterrows():
if (visit_row['CUST_ID'] == cust_row['CUST_ID']):
if cust_row['START_DTM'] <= visit_row['VISIT_DTM'] <= cust_row['END_DTM']:
attr_array.append(str(cust_row['ATTR']))
visit_df.at[index, 'ATTR_STR'] = '-'.join(attr_array)
visit_df.at[index, 'ATTR_ARRAY'] = attr_array
uj5u.com熱心網友回復:
您擁有的資料由數學階躍函式描述,為此目的,staircase建立在 pandas 和 numpy 上。
與熊貓一起作業會很好,Timestamp因此,除了您提供的設定代碼之外,還運行以下命令
visit_df["VISIT_DTM"] = pd.to_datetime(visit_df["VISIT_DTM"])
customer_df["START_DTM"] = pd.to_datetime(customer_df["START_DTM"])
customer_df["END_DTM"] = pd.to_datetime(customer_df["END_DTM"])
解決方案
我們將為每個客戶和顏色(CUST_ID 和 ATTR)創建一個階梯函式。階梯函式由 staircase.Stairs 類表示。這個類是樓梯,就像系列是熊貓一樣。為此,我們將這些變數上的資料幀分組,并將子資料幀傳遞給樓梯建構式。
import staircase as sc
stepfunctions = customer_df.groupby(["CUST_ID", "ATTR"]).apply(sc.Stairs, "START_DTM", "END_DTM")
我們的stepfunctions變數看起來像這樣。它是一個具有多索引的系列,值為 Stairs 物件。
CUST_ID ATTR
1 BLACK <staircase.Stairs, id=2516845521032>
BLUE <staircase.Stairs, id=2516845756680>
RED <staircase.Stairs, id=2516845833800>
20 BLACK <staircase.Stairs, id=2516843896648>
BLUE <staircase.Stairs, id=2516845647752>
YELLOW <staircase.Stairs, id=2516845788808>
dtype: object
接下來,我們將創建一個函式,給定一個客戶 id,從該客戶中提取訪問時間visit_df并采樣該客戶的 stepfunction,回傳一個資料幀。
def check_customer_visit(customer):
visit_times = visit_df.query(f"CUST_ID == {customer}")["VISIT_DTM"]
return sc.sample(stepfunctions[customer], visit_times).melt(ignore_index=False).assign(CUST_ID = customer)
運行這個customer = 1給出
ATTR VISIT_DTM value CUST_ID
BLACK 2009-08-28 0 1
BLUE 2009-08-28 1 1
RED 2009-08-28 0 1
BLACK 2009-08-31 1 1
BLUE 2009-08-31 1 1
RED 2009-08-31 0 1
A valueof 0 表示該屬性在該訪問期間不適用。
因此,為每個客戶執行此操作并連接資料幀
data = pd.concat([check_customer_visit(customer) for customer in visit_df["CUST_ID"].unique()])
然后我們可以重置索引,過濾應用屬性的行并洗掉value列
data.reset_index().query("value == 1").drop(columns="value")
這給你
ATTR VISIT_DTM CUST_ID
1 BLUE 2009-08-28 1
3 BLACK 2009-08-31 1
4 BLUE 2009-08-31 1
7 BLUE 2009-08-27 20
8 YELLOW 2009-08-27 20
9 BLACK 2009-08-31 20
10 BLUE 2009-08-31 20
這是整潔的資料格式。如果你想要得到它進入您所提交,那么你可以GROUPBY客戶和訪問時間和應用的格式list到ATTR列。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/335472.html
