簡體   English   中英

Pandas 列取決於其先前的值(行)?

[英]Pandas column that depends on its previous value (row)?

我想在我的 dataframe 中創建第三列,這取決於一行中的新列和現有列。

這個新列應該從 0 開始。

我希望我的第 3 列從 0 開始。

它的下一個值是它的前一個值加上df.below_lo[i] (如果前一個值為 0)。

如果它的前一個值是 1,它的下一個值是它的前一個值加上df.above_hi[i]

我想我有兩個問題:如何啟動第 3 列以及如何使其依賴於自身。

import pandas as pd
import math

data = {'below_lo': [0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
        'above_hi': [0, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0]}

df = pd.DataFrame(data)

df['pos'] = math.nan
df['pos'][0] = 0

for i in range(len(df.below_lo)):
    if df.pos[i] == 0:
        df.pos[i+1] = df.pos[i] + df.below_lo[i]
    if df.pos[i] == 1:
        df.pos[i+1] = df.pos[i] + df.above_hi[i]

print(df)

所需的 output 是:

    below_lo  above_hi  pos
0        0.0       0.0  0.0
1        1.0       0.0  0.0
2        0.0      -1.0  1.0
3        0.0       0.0  0.0
4        0.0      -1.0  0.0
5        0.0       0.0  0.0
6        0.0      -1.0  0.0
7        0.0       0.0  0.0
8        0.0       0.0  0.0
9        1.0       0.0  0.0
10       0.0       0.0  1.0
11       0.0       0.0  1.0
12       0.0       0.0  1.0
13       NaN       NaN  1.0

上面的代碼產生了正確的 output,除了我還收到一些錯誤消息:

試圖在 DataFrame 的切片副本上設置值

如何清理此代碼以使其運行而不拋出此警告? ?

使用.loc

df.loc[0, 'pos'] = 0

for i in range(len(df.below_lo)):
    if df.loc[i, 'pos'] == 0:
        df.loc[i+1, 'pos'] = df.loc[i, 'pos'] + df.loc[i, 'below_lo']
    if df.loc[i, 'pos'] == 1:
        df.loc[i+1, 'pos'] = df.loc[i, 'pos'] + df.loc[i, 'above_hi']

感謝@Michael O.已經接受了一個很好的回答,但是如果你不喜歡像不完全Pandas-esque那樣對行進行迭代,這里有一個沒有顯式循環遍歷行的解決方案:

from functools import reduce
res = reduce(lambda d, _ : 
    d.fillna({'pos':d['pos'].shift(1) 
            + (d['pos'].shift(1)  == 0) * d['below_lo'] 
            + (d['pos'].shift(1)  == 1) * d['above_hi']}), 
        range(len(df)), df)
res

生產

      below_lo    above_hi    pos
--  ----------  ----------  -----
 0           0           0      0
 1           1           0      1
 2           0          -1      0
 3           0           0      0
 4           0          -1      0
 5           0           0      0
 6           0          -1      0
 7           0           0      0
 8           0           0      0
 9           1           0      1
10           0           0      1
11           0           0      1
12           0           0      1

誠然,它的效率有點低,語法也有點模糊。 但它可以寫在一行上(即使為了清楚起見我把它分成了幾行)!

這個想法是,我們可以通過傳遞值來使用fillna(..) function,該值是根據“pos”的先前值(因此shift(1) )和“below_lo”和“above_hi”的當前值計算得出的。 這里的額外復雜之處在於,此操作只會為具有非 NaN 值的行的正下方的行填充非NaN 因此我們需要重復應用這個 function 直到所有的 NaN 都被填滿,這就是reduce發揮作用的地方

暫無
暫無

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

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