我有一個包含開始時間、結束時間、用戶、產品和使用率記錄的資料幀。用戶能夠以不同的速率多次使用相同的產品。我想將此 DataFrame 轉換為時間序列資料集,其中為每個用戶創建 4 小時的 bin,其中使用率相加。由于開始時間和結束時間可能與 bin 邊界重疊,因此需要計算該 bin 的部分使用量,并且每個產品都會收到自己的列。
原始資料幀:
| 開始 | 結尾 | 用戶 | 產品 | 使用率 |
|---|---|---|---|---|
| 1 | 12 | 一種 | X_1 | 10 |
| 8 | 15 | 一種 | X_1 | 20 |
| 3 | 7 | 乙 | X_1 | 3 |
| 3 | 8 | 乙 | X_2 | 70 |
期望的輸出:
| 用戶 | 垃圾桶 | 開始 | 結尾 | X_1 | X_2 |
|---|---|---|---|---|---|
| 一種 | 0-4 | 0 | 4 | 30 | 0 |
| 一種 | 4-8 | 4 | 8 | 40 | 0 |
| 一種 | 8-12 | 8 | 12 | 120 | 0 |
| 一種 | 12-16 | 12 | 16 | 60 | 0 |
| 乙 | 0-4 | 0 | 4 | 3 | 70 |
| 乙 | 4-8 | 4 | 8 | 9 | 280 |
我試圖用來pd.cut創建垃圾箱,但只能設法創建開始時間匹配和/或結束時間匹配的資料幀,而不是中間的垃圾箱。我想防止使用 for 回圈,因為當將其擴展到 10k 用戶和 20 個產品時,這些回圈會變得非常慢。程序我認為第一重復的每一行時間塊的所要求的數量(0-4,4-8,8-12用于第一記錄),計算該倉內的持續時間,持續時間乘以通過usage_rate獲得used_in_bin的值,則groupby(['user', 'bin'])和檢索這些used_in_bin值的總和。然后最后一步是旋轉產品名稱和值以獲取表格。
困難的部分是我一直在為時間范圍(日期時間或數字)創建時間箱。在我的范圍的開始和結束時間之間,我可以通過什么方式為丟失的 bin 創建重復記錄?
uj5u.com熱心網友回復:
您擁有的資料由數學階躍函式描述,為此目的,
您想要做的是創建垃圾箱并集成(找到下方的區域)這些步驟功能。對于階躍函式,sf這意味著以下計算
sf.slice([0,4,8,12,16]).integral()
我們可以用它pandas.Series.apply來為我們所有的步驟函式做這件事。
binned = stepfunctions.apply(lambda sf: sf.slice([0,4,8,12,16]).integral())
The binned variable will we a dataframe, with the same index as stepfunctions, with a column for each bin interval
[0, 4) [4, 8) [8, 12) [12, 16)
user product
A X_1 30.0 40.0 120.0 60.0
B X_1 3.0 9.0 0.0 0.0
X_2 70.0 280.0 0.0 0.0
To get this data in a tidy format the following can be used
tidy_result = binned.melt(ignore_index=False).rename({"variable":"bin"}).reset_index()
The tidy_result dataframe will look like this:
user product bin value
0 A X_1 [0, 4) 30.0
1 B X_1 [0, 4) 3.0
2 B X_2 [0, 4) 70.0
3 A X_1 [4, 8) 40.0
4 B X_1 [4, 8) 9.0
5 B X_2 [4, 8) 280.0
6 A X_1 [8, 12) 120.0
7 B X_1 [8, 12) 0.0
8 B X_2 [8, 12) 0.0
9 A X_1 [12, 16) 60.0
10 B X_1 [12, 16) 0.0
11 B X_2 [12, 16) 0.0
This may be enough for your purposes. If you want to get it in the exact format you have submitted, then this should be easy enough:
- use
tidy_result.pivot(index=["user", "bin"], columns="product")to turn the product column into columns for each product. FillNAvalues forAandX_2with 0. - use
tidy_result["start"] = pd.IntervalIndex(tidy_result["bin"]).leftetc
To recap, the solution (after imports) boils down to the following three lines
stepfunctions = df.groupby(["user", "product"]).apply(sc.Stairs, "start", "end", "usage_rate")
binned = stepfunctions.apply(lambda sf: sf.slice([0,4,8,12,16]).integral())
tidy_result = binned.melt(ignore_index=False).rename({"variable":"bin"}).reset_index()
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/334471.html
上一篇:df.dropna()修改行索引
