Chciałbym pomóc w zgrupowaniu kolejnych wierszy, gdy przekroczony jest dany próg Cumms. Cumsum należy również ponownie uruchomić (do zera), gdy ten próg zostanie przekroczony, jako taki:

Index  Values       Regular CumSum  Wanted CumSum  Wanted Column
1      0.0666666666    0.0666666666    0.000000    0.0
2      0.0238095238    0.0904761904    0.000000    1.0
3      0.0134146341    0.1038908246    0.000000    2.0
4      0.0210135970    0.1249044216    0.013414    2.0
5      0.0072639225    0.1321683441    0.000000    3.0
6      0.0158536585    0.1480220027    0.007263    3.0
7      0.0012004801    0.1492224829    0.000000    4.0
8      0.0144230769    0.1636455598    0.001200    4.0
9      0.0130331753    0.1766787351    0.015623    4.0

W tym przypadku próg wynosi 0,02 (przepraszam za wszystkie dziesiętne).

  • Wszelkie wejście większe następnie próg powinien natychmiast utworzyć lub zamknąć grupę (takich jak wpisy w indeksie 1,2 i 4)
  • Wpis na indeksu 3 jest mniejszy niż próg, więc czeka na kolejny kolejny wpis. Jeśli następny wpis (indywidualnie lub podsumowany do indeksu 3 wartości) przekroczy próg, tworzą nową grupę, w przeciwnym razie zostanie włączony następny następny wpis (w tym przypadku wpis indeksu 4 jest większy niż próg, więc utworzona jest nowa grupa ).
  • Wejście 5 jest mniejsze niż próg 0,02, ale wejście sumującego 6, sprawia, że są większe niż 0,02, stąd grupa jest zamknięta.
  • Wpisy 7,8 i 9 zsumowane razem są większe niż 0,02, tworząc w ten sposób grupę.
  • ....

Byłem w stanie opracować następujący prosty kod, aby to osiągnąć, ale miałem nadzieję, że ktoś może pomóc mi rozwinąć szybszą metodę, może wykorzystać bibliotekę Pandas:

FinalList = [0]
index=0
cumsum = 0
i=1
#while to go through all entries in df
while(i!=df.index[-1]): 
    #When entry is larger(or equal) than threshold immediately close group and clear cumsum
    if df.Values.iloc[i] >= Threshold:
        FinalList.append(index)
        cumsum = 0
        index+=1
    #When entry is smaller than threshold
    if df.Values.iloc[i] < Threshold:
        #If previous cumsum plus current entry surpass threshold group is closed.       
        if cumsum + df.Values.iloc[i] > Threshold:
                FinalList.append(index)
                cumsum=0
                index+=1
            #Otherwise, continue increasing cumsum until it crosses threshold
            else:
                cumsum = cumsum + df.Values.iloc[i]
                FinalList.append(index)
        i+=1
2
StefanSmeisters 1 marzec 2019, 03:12

2 odpowiedzi

Najlepsza odpowiedź

Łącząc odpowiedzi @P Maschoff's and @ Allolz Opracowałem następujący kod, którego czas wykonania (przy użyciu zestawu danych z czasem wykonania ponad 15 sekund za pomocą kodu w moim pierwotnym pytaniu) zostało zredukowane do poniżej sekundy:

@njit
def dynamic_cumsum(seq, max_value):
    FinalList = [0]
    cumsum = 0
    running = 0
    for i in prange(len(seq)):
        cumsum += seq[i]
        if cumsum >= max_value:
            cumsum = 0
            running += 1        
        FinalList.append(running)
    return FinalList
0
StefanSmeisters 3 marzec 2019, 12:41

Im więcej niż {{x0}

threshold = 0.02
cumsum = 0
group = 0
for idx, value in df.Values.iteritems():
    cumsum += value
    df.loc[idx, 'Group'] = group
    if cumsum >= threshold:
        cumsum = 0
        group += 1
         Values  Group
Index                 
1      0.066667    0.0
2      0.023810    1.0
3      0.013415    2.0
4      0.021014    2.0
5      0.007264    3.0
6      0.015854    3.0
7      0.001200    4.0
8      0.014423    4.0
9      0.013033    4.0

To nie robi szczególnie fantazyjne, ale powinno być szybsze tylko dlatego, że robi mniej operacji indeksowania i ogólnie operacji. Jeśli chcesz dowiedzieć się więcej o tym, jak napisać pandas kod stylu, polecam Ta seria blogów przez jednego z jego programistów.

1
P Maschhoff 1 marzec 2019, 03:08