[英]filter pandas rows by other dataframe columns
我有3個dataframes
p_id
已經按日期和p_id
排序,沒有null
值,如:
第一個數據框
df1 = pd.DataFrame([['2018-07-05',8.0,1],
['2018-07-15',1.0,1],
['2018-08-05',2.0,1],
['2018-08-05',2.0,2]],
columns=["purchase_date", "qty", "p_id"])
第二個DataFrame
df2 = pd.DataFrame([['2018-07-15',2.0,1],
['2018-08-04',7.0,1],
['2018-08-15',1.0,2]],
columns=["sell_date", "qty", "p_id"])
第三數據框
df3 = pd.DataFrame([['2018-07-25',1.0,1],
['2018-08-15',1.0,1]],
columns=["expired_date", "qty", "p_id"])
dataframe
看起來像:
第一名:( 持有購買詳情)
purchase_date qty p_id
0 2018-07-05 8.0 1
1 2018-07-15 1.0 1
2 2018-08-05 2.0 1
3 2018-08-05 2.0 2
第二名:( 持有銷售明細)
sell_date qty p_id
0 2018-07-15 2.0 1
1 2018-08-04 7.0 1
2 2018-08-15 1.0 2
第三名:( 保留有效期的詳細信息)
expired_date qty p_id
0 2018-07-25 1.0 1
1 2018-08-15 1.0 1
現在,我想做的是查找已過期產品的購買時間
以下FIFO
(先購買的產品將先失效)
截止日期2018-07-15
我們有8 + 1的購買數量和-2的銷售數量,即庫存中總共有8 + 1-2數量, -ve
符號表示數量扣減
截止日期2018-07-25
1個數量已過期,因此新的when_product_expired
dataframe
when_product_expired
第一個條目將為:
purchase_date expired_date p_id
2018-07-05 2018-07-25 1
截止日期2018-08-04
已售完7個數量,所以當前數量為8 + 1-2-7 = 0
截止日期2018-08-05
購買了2個數量,所以當前數量為0 + 2
截止日期2018-08-15
1個數量已過期
因此,新的最終條目將是:
purchase_date expired_date p_id
2018-07-05 2018-07-25 1
2018-08-05 2018-08-15 1
這次產品過期是在2018-07-25購買的產品
實際上我有約會時間,所以買賣時間永遠不會相等(您可能會假設),而且在買賣和到期之前,總會有一定數量的庫存產品,即數據是一致的
並預先感謝您:-)
我現在想的是將所有日期字段重命名為相同的字段名稱,並在購買,出售,過期的dataframe
框后加上負號,但這對我沒有幫助
df2.qty = df2.qty*-1
df3.qty=df3.qty*-1
new = pd.concat([df1,df2, df3],sort=False)
.sort_values(by=["purchase_date"],ascending=True)
.reset_index(drop=True)
您本質上想要的是此FIFO庫存清單。 以我的經驗,大熊貓不是將不同行彼此關聯的正確工具。 工作流程應為“拆分應用”組合。 如果您將其拆分,卻沒有真正找到將其重新拼合的方法,則可能是一個格式錯誤的問題。 您仍然可以通過groupby來完成很多工作,但這是我不會嘗試通過一些巧妙的熊貓技巧來解決的。 即使您使它起作用,也很難維護。
我不知道您的問題對性能有多重要(即您的數據框有多大)。 如果只有10000個條目,則可以顯式循環遍歷熊貓行(警告:這很慢),並手動構建fifo列表。
我為此整理了一些代碼。 您建議的DateFrame在其中。 我遍歷所有行,並記賬有多少庫存。 這在隊列q
完成,隊列q
中包含每個項目的元素,並且該元素方便地是purchase_date。
import queue
import pandas as pd
from pandas import Series, DataFrame
# modified (see text)
df1 = pd.DataFrame([['2018-07-05',8.0,1],
['2018-07-15',3.0,1],
['2018-08-05',2.0,1],
['2018-08-05',2.0,2]],
columns=["purchase_date", "qty", "p_id"])
df2 = pd.DataFrame([['2018-07-15',2.0,1],
['2018-08-04',7.0,1],
['2018-08-15',1.0,2]],
columns=["sell_date", "qty", "p_id"])
df3 = pd.DataFrame([['2018-07-25',1.0,1],
['2018-08-15',1.0,1]],
columns=["expired_date", "qty", "p_id"])
df1 = df1.rename(columns={'purchase_date':'date'})
df2 = df2.rename(columns={'sell_date':'date'})
df3 = df3.rename(columns={'expired_date' : 'date'})
df3['qty'] *= -1
df2['qty'] *= -1
df = pd.concat([df1,df2])\
.sort_values(by=["date"],ascending=True)\
.reset_index(drop=True)
# Necessary to distinguish between sold and expried items while looping
df['expired'] = False
df3['expired'] = True
df = pd.concat([df,df3])\
.sort_values(by=["date"],ascending=True)\
.reset_index(drop=True)
#date qty p_id expired
#7-05 8.0 1 False
#7-15 1.0 1 False
#7-15 -2.0 1 False
#7-25 -1.0 1 True
#8-04 -7.0 1 False
#8-05 2.0 1 False
#8-05 2.0 2 False
#8-15 -1.0 2 False
#8-15 -1.0 1 True
# Iteratively build up when_product_expired
when_product_expired = []
# p_id hardcoded here
p_id = 1
# q contains purchase dates for all individual items 'currently' in stock
q = queue.Queue()
for index, row in df[df['p_id'] == p_id].iterrows():
# if items are bought, put as many as 'qty' into q
if row['qty'] > 0:
for tmp in range(int(round(row['qty']))):
date = row['date']
q.put(date)
# if items are sold or expired, remove as many from q.
# if expired additionaly save purchase and expiration date into when_product_expired
elif row['qty'] < 0:
for tmp in range(int(round(-row['qty']))):
purchase_date = q.get()
if row['expired']:
print 'item p_id 1 was bought on', purchase_date
when_product_expired.append([purchase_date, row['date'], p_id])
when_product_expired = DataFrame(when_product_expired, columns=['purchase_date', 'expired_date', 'p_id'])
幾點評論:
我依靠你的保證人
在銷售和到期之前,總會有一定數量的產品庫存
您的示例DataFrames沒有給出此信息。 在2018-07-25之前,有9個項目的p_id 1已購買且9被出售。 沒有什么庫存可以過期。 我修改了df1,以便購買了11件。
.groupby('p_id').apply(function)
或在df['p_id'].unique()
循環將其推廣到更多p_id df['p_id'].unique()
因此,盡管這不是可擴展的解決方案,但我希望它能對您有所幫助。 好看
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.