簡體   English   中英

在大熊貓的最近發生的情況中滾動m

[英]Rolling m out of n most recent occurences of condition in pandas

我對符合條件的最后'n'事件中的'm'次數感興趣,按人或用戶分組 具體來說,我感興趣的是玩家是否習慣於在給定的班級或“類別”中玩游戲,這取決於他們最后幾場比賽(而不是任何比賽)中有多少比賽是在指定等級或高於指定等級。

我盡職盡責地打破了一個玩具數據集中的一個小組,然后讓我的代碼在下面工作。 但是,當我嘗試在SeriesGroupBy對象上隨意使用相同的方法鏈時,事情會發生故障。

首先,最簡單的例子。 當玩家3的前3個匹配中的2個屬於類別3時,列hc (高等級)為1否則,它為0.(我手動生成此並使用0 | 1,而不是True | False。):

import pandas as pd
pd.__version__
# '0.23.4'
match = ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c',
         'c', 'c', 'd', 'd', 'd', 'e', 'e', 'e', 'e']
category = [3, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2]
player = ['bar', 'baz', 'chaz', 'baz', 'choo', 'chaz', 'chaz', 'foo',
          'baz', 'choo', 'foo', 'char', 'baz', 'choo', 'foo', 'chaz', 'baz']
hc = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1]
games = pd.DataFrame({'match': match, 'category': category, 'player': player, 'hc': hc})
games

#    match  category player  hc
# 0      a         3    bar   0
# 1      a         3    baz   0
# 2      a         3   chaz   0
# 3      b         2    baz   0
# 4      b         2   choo   0
# 5      b         2   chaz   0
# 6      c         3   chaz   0
# 7      c         3    foo   0
# 8      c         3    baz   0
# 9      c         3   choo   0
# 10     d         3    foo   0
# 11     d         3   char   0
# 12     d         3    baz   1
# 13     e         2   choo   0
# 14     e         2    foo   1
# 15     e         2   chaz   1
# 16     e         2    baz   1

由於我之前的漫長努力而充分受阻,我采用了(顯然是天真的)策略來打破一個有趣的玩家並讓計算在拆分組上工作:

baz = games.groupby('player').get_group('baz')
baz

#    match  category player  hc
# 1      a         3    baz   0
# 3      b         2    baz   0
# 8      c         3    baz   0
# 12     d         3    baz   1
# 16     e         2    baz   1

result = baz.category.gt(2).rolling(3).sum().shift().gt(1)
result

# 1     False
# 3     False
# 8     False
# 12     True
# 16     True
# Name: category, dtype: bool

成功! 我是熊貓黑客! 我已經升天了,現在可以用Pandoric Way來輔導別人了! 在我購買長袍並在修道院收到我分配的嬰兒床之前,先讓我快速檢查一下:

games.groupby('player').category.gt(2).rolling(3).sum().shift().gt(1)

回溯(最近一次調用最后一次):文件“”,第1行,在文件“(枯燥的路徑東西)/lib/python3.6/site-packages/pandas/core/groupby/groupby.py”,第762行,在getattr中 return self._make_wrapper(attr)文件“(枯燥的路徑東西)/lib/python3.6/site-packages/pandas/core/groupby/groupby.py”,第799行,在_make_wrapper中引發AttributeError(msg)AttributeError:無法訪問'SeriesGroupBy'對象的可調用屬性'gt',嘗試使用'apply'方法

啊。 我是暴徒。

這樣做有什么好處? 還有,我做錯了什么? 在元級別,為什么我的策略在單個組上運行然后推廣不起作用? 我確實嘗試了apply()方式。 它輸出廢話。

編輯: apply()可能答案:

games['actual_hc'] =
    games.groupby('player').category.apply(lambda x: x.shift().gt(2).rolling(3).sum().fillna(0, downcast='infer').astype(int).gt(1))
games

#    match  category player  hc  actual_hc
# 0      a         3    bar   0      False
# 1      a         3    baz   0      False
# 2      a         3   chaz   0      False
# 3      b         2    baz   0      False
# 4      b         2   choo   0      False
# 5      b         2   chaz   0      False
# 6      c         3   chaz   0      False
# 7      c         3    foo   0      False
# 8      c         3    baz   0      False
# 9      c         3   choo   0      False
# 10     d         3    foo   0      False
# 11     d         3   char   0      False
# 12     d         3    baz   1       True
# 13     e         2   choo   0      False
# 14     e         2    foo   1       True
# 15     e         2   chaz   1       True
# 16     e         2    baz   1       True

這在我的實際250k行DataFrame上大約需要12秒。 我仍然喜歡更快的東西,只要知道“正確的方式”,如果有的話。

使用申請:

games.groupby('player').apply(
    lambda group: group.category.gt(2).rolling(3).sum().shift().gt(1)
)

這輸出:

player    
bar     0     False
baz     1     False
        3     False
        8     False
        12     True
        16     True
char    11    False
chaz    2     False
        5     False
        6     False
        15     True
choo    4     False
        9     False
        13    False
foo     7     False
        10    False
        14    False
Name: category, dtype: bool

這似乎是你想要的。

我不知道這是否是性能最好的,但由於錯誤建議使用apply,我猜猜大熊貓的開發人員認為這是一個好主意。

我最近重新審視了這個問題並發現了答案, transform() 出於某種原因,pj.dewitte的apply()的回答對rolling()的min_periods參數不敏感,無論我在鍵入min_periods=2時按下鍵有多難。

完整答案:

games['actual_hc'] = \
    games.groupby('player').category.transform(
        lambda g:
        g.gt(2).rolling(3, min_periods=2).sum().shift().gt(1)).astype(int)
#    match  category player  hc  actual_hc
# 0      a         3    bar   0          0
# 1      a         3    baz   0          0
# 2      a         3   chaz   0          0
# 3      b         2    baz   0          0
# 4      b         2   choo   0          0
# 5      b         2   chaz   0          0
# 6      c         3   chaz   0          0
# 7      c         3    foo   0          0
# 8      c         3    baz   0          0
# 9      c         3   choo   0          0
# 10     d         3    foo   0          0
# 11     d         3   char   0          0
# 12     d         3    baz   1          1
# 13     e         2   choo   0          0
# 14     e         2    foo   1          1
# 15     e         2   chaz   1          1
# 16     e         2    baz   1          1

請注意,即使foo在她的最后一場比賽之前只有兩場比賽,他們都是三級,並且她被正確地報告為games.iloc[14]的高級球員。

暫無
暫無

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

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