簡體   English   中英

如何循環分組數據框

[英]How to Loop Through Grouped Dataframe

我是 python 的超級新手,但直接嘗試使用 Pandas 等分析工具找出現實世界中的問題。

我已經從 csv 導入了數據,但這里有一個小的數據復制:

df2 = pd.DataFrame({'SKU': [22335, 22335, 22335, 22335, 33442, 33442, 33442, 33442],
                'Date': ['2019-12-31', '2020-01-07', '2020-01-14', '2020-01-21', '2019-12-31', '2020-01-07', '2020-01-14', '2020-01-21'],
                'Urgent': [10,8,4,20,50,45,65,32],
                'Delivered': [4,7,12,10, 35,75,23,42]})

有兩個項目 SKU 編號,22335 和 33442,一周開始日期,每周緊急設備請求和每周設備交付數量。 在這一點上,我已經弄清楚如何在整個數據集上計算一個 for 循環,每行引用前一行的計算值:

# Create new numeric column 'Result'
df['Result'] = np.nan

# Assign initial value for the first row of 'Result' (Should be first row in each SKU group)
df.loc[0, 'Result'] = df.loc[0, 'Delivered'] + df.loc[1, 'Delivered'] - df.loc[0, 'Urgent']

# Loop through each row except for last row to calculate
for i in range(1, len(df)-1):
    df.loc[i,'Result'] = max(df.loc[i-1, 'Result'], 0) + df.loc[i+1, 'Delivered'] - df.loc[i, 'Urgent']

print(df)

但是,我的下一步是僅對每個單獨的 SKU(分別為 22335 和 33442)執行上述操作。 我嘗試使用 groupby 按日期按 SKU 對每一行進行排名,但我不知道如何在循環中引用它:

# Convert Date datatype
df['Date'] = pd.to_datetime(df['Date'])

# Use groupby to create ranking by SKU and Date
df['SKURank'] = df.groupby('SKU')['Date'].rank(ascending = True).astype('int64')

我曾嘗試定義一個函數,該函數可以為每次迭代引用它自己的輸出,然后使用 .apply 樣式循環調用它,但沒有成功,但說實話,我完全迷失了。

我也嘗試遵守拆分、應用、組合原則並按 SKU 對我的數據進行分組,應用循環,然后將所有行重新組合在一起,但我真的不知道從哪里開始。

以下是我的主要問題:

對於每個單獨的 SKU 組,我應該使用哪種循環來執行與上述代碼相同的任務(返回組中第一行的初始值,然后循環遍歷每個后續行)?

如果推薦的循環形式(不管性能如何,我還沒有那么高)要求我事先定義一個函數,我將如何創建一個函數,該函數為每個第一行之后的每一行引用它自己的輸出單品?

更新:

天啊。 親愛的上帝,我創造了什么……這……太惡心了……

是的,我用嵌套的 if 語句創建了一個巨大的 for 循環。 是的,這太可怕了。 不,它並沒有做我需要的所有事情,就像在數據幀的最后一行執行循環一樣。 如果下面的任何部分有意義,並且您可以向我指出如何使其真正起作用的方向,我會很感激一些建議。

import pandas as pd
import numpy as np

# Create dataframe for two SKUs, a weekly process date, urgent requested quantity, and delivered quantity
df = pd.DataFrame({'SKU': [22335, 22335, 22335, 22335, 33442, 33442, 33442, 33442],
                    'Date': ['2019-12-31', '2020-01-07', '2020-01-14', '2020-01-21', '2019-12-31', '2020-01-07', '2020-01-14', '2020-01-21'],
                    'Urgent': [10,8,4,20,50,45,65,32],
                    'Delivered': [4,7,12,10, 35,75,23,42]})

# Create new numeric column 'Result'
df['Result'] = np.nan

# Convert Date datatype and create 3 necessary columns
df['Date'] = pd.to_datetime(df['Date'])
df['Result'] = np.nan
df['WeeklyMiss'] = np.nan
df['Logic'] = ''

# Create list of unique SKUs in dataframe
skulst = df.SKU.unique()

print(skulst)


# Set initial indeces value 
skunum = 0
i = 0

# While loop with nested for loop to iterate over the dataframe
while skunum <= len(skulst):
    for i in range(0, len(df)-1):
        # Calculate first SKU row
        if i == 0 and df.loc[i, 'SKU'] == skulst[skunum]: 
            df.loc[i, 'Result'] = max(df.loc[i, 'Delivered'] + df.loc[i+1, 'Delivered'] - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'WeeklyMiss'] = min(df.loc[i, 'Delivered'] + df.loc[i+1, 'Delivered'] - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'Logic'] = 'First Row'
        # Calculate next SKU rows
        elif i > 0 and df.loc[i, 'SKU'] == skulst[skunum] and df.loc[i+1,'SKU'] == skulst[skunum]:
            df.loc[i, 'Result'] = max(df.loc[i+1, 'Delivered'] + min(df.loc[i-1, 'Result'], df.loc[i, 'Delivered']) - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'WeeklyMiss'] = min(df.loc[i-1, 'Result'] + df.loc[i+1, 'Delivered'] - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'Logic'] = 'Next SKU Row'
        # Calculate last SKU row
        elif i > 0 and df.loc[i, 'SKU'] == skulst[skunum] and (df.loc[i+1,'SKU'] != skulst[skunum] or i == len(df)):
            df.loc[i, 'Result'] = max(df.loc[i-1, 'Result'] - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'WeeklyMiss'] = min(df.loc[i-1, 'Result'] - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'Logic'] = 'Last SKU Row'
        
            
        # Calculate first SKU row and switch to next SKU 
        elif i > 0 and i < len(df) and df.loc[i, 'SKU'] != skulst[skunum] and df.loc[i-1,'SKU'] == skulst[skunum] :
            df.loc[i, 'Result'] = max(df.loc[i, 'Delivered'] + df.loc[i+1, 'Delivered'] - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'WeeklyMiss'] = min(df.loc[i, 'Delivered'] + df.loc[i+1, 'Delivered'] - df.loc[i, 'Urgent'], 0)
            df.loc[i, 'Logic'] = 'First SKU Row'
            if skunum + 1 <= len(skulst):
                skunum += 1
            else:
                df.loc[i, 'Result'] = max(df.loc[i-1, 'Result'] - df.loc[i, 'Urgent'], 0)
                df.loc[i, 'WeeklyMiss'] = min(df.loc[i-1, 'Result'] - df.loc[i, 'Urgent'], 0)
                df.loc[i, 'Logic'] = 'Last SKU Row'
                continue
    else:
        print(df)
        break

請參閱 Pandas 文檔中的Group By: split-apply-combine指南,了解如何迭代組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM