簡體   English   中英

使用pandas dataframe填寫Python中的查找表並聚合function

[英]Fill in lookup table in Python using pandas dataframe and aggregate function

我有一個 pandas dataframe 包含不同日期的(商店,產品,價格)信息,就像今天這樣。

df = pd.DataFrame(data={'day': [1, 2, 3, 1, 2, 3, 2, 4, 5, 2, 4, 5, 2, 4, 5, 2, 4, 5],
                        'shop': ['a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c'],
                        'product': ['x', 'x', 'x', 'y', 'y', 'y', 'x', 'x', 'x', 'z', 'z', 'z', 'y', 'y', 'y', 'z', 'z', 'z'],
                        'price': [0, 1, 2, 2, 4, 6, 1, 2, 3, 0, 1, 1, 1, 1, 0, 2, 2, 2]})

我想制作一個查找表,為每個(商店、產品)組合提供最近兩天的平均價格。

例如,給定商店“a”和產品“y”,價格分別為 2、4 和 6,因此查找表中的結果應該是 4 和 6 的平均值,即 5。

預期結果是以下嵌套字典:

{'a': {'x': 1.5, 'y': 5.0},
 'b': {'x': 2.5, 'z': 1.0},
 'c': {'y': 0.5, 'z': 2.0}}

我想出了兩個解決方案。

#Solution 1:嵌套for循環

lookup = {}
for categ_1 in df['shop'].unique():
    df_1 = df[df['shop'] == categ_1]
    lookup[categ_1] = {}
    for categ_2 in df_1['product'].unique():
        df_2 = df_1[df_1['product'] == categ_2]
        res = df_2.iloc[-2:,:]['price'].mean()
        lookup[categ_1][categ_2] = res

#Solution 2:過濾(商店,產品)的獨特組合並迭代它們

lookup = {}
for i, row in df[['shop', 'product']].drop_duplicates().iterrows():
    mask = ((df['shop'] == row['shop']) & (df['product'] == row['product']))
    _df = df[mask]
    res = _df.iloc[-2:,:]['price'].mean()
    try:
        lookup[row['shop']].update({row['product']: res})
    except KeyError:
        lookup[row['shop']] = {row['product']: res}

雖然我發現解決方案 2 更優雅,但解決方案 1 更快。

  • 解決方案 1:每個循環 7.57 毫秒 ± 1.25 毫秒(7 次運行的平均值 ± 標准偏差,每次 100 次循環)
  • 解決方案 2:每個循環 9.3 ms ± 1.04 ms(7 次運行的平均值 ± 標准偏差,每次 100 次循環)

我的實際 dataframe 包含更多的列和更多的行來迭代,所以我想,如果可能的話,避免像解決方案 1 中那樣的嵌套for循環,但也是比解決方案 2 更快的解決方案。

如果您能改進其中一種解決方案,或找到更好的解決方案,我將很高興

謝謝

Pandas 有一個groupby function 非常適合這個。

lookup = df.groupby(['shop', 'product'])

這為您提供了一個 groupby object。接下來的挑戰是如何根據最近兩天聚合您的列,因為這並不是 GroupBy 本身內置的。 您可以創建一個 lambda function 來獲取每個價格列表中的最后兩項並計算平均值。

df.sort_values(by='day', ascending=True, inplace=True)
avg_func = lambda x: sum(x[-2:])/2
lookup = df.groupby(['shop', 'product']).agg({'price': avg_func})

Output:

shop product       
a    x          1.5
     y          5.0
b    x          2.5
     z          1.0
c    y          0.5
     z          2.0
 

暫無
暫無

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

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