簡體   English   中英

在數據幀熊貓中迭代行減去1

[英]Iterating over rows subtracting by 1 in dataframe pandas

我有一個熊貓數據框,我想從最后一個非Null值進行迭代,然后從該值中減去1。

z = pd.DataFrame({'l':range(10),'r':[4,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan]\
             ,'gh':[np.nan,np.nan,np.nan,np.nan,15,np.nan,np.nan,np.nan,np.nan,np.nan],\
             'gfh':[np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,2]})
df = z.transpose().copy()
df.reset_index(inplace=True)
df.drop(['index'],axis=1, inplace=True)
df.columns = ['a','b','c','d','e','f','g','h','i','j']


In [8]: df
Out[8]: 
    a   b   c   d   e   f   g   h   i   j
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN   2
1 NaN NaN NaN NaN  15 NaN NaN NaN NaN NaN
2   0   1   2   3   4   5   6   7   8   9
3   4 NaN NaN NaN NaN NaN NaN NaN NaN NaN

我有上面的數據框,我想將每一行減少1,直到最后一列。 例如第2行的值是15,所以我要跟隨14、13、12、11、10。 由於沒有剩余的列,因此第一行中的2不會跟隨任何內容。 同樣,最后一行中的4將是3,2,1,0,0,0,0等。

通過執行以下操作,我達到了所需的輸出。

for index, row in df.iterrows():
    df.iloc[index,df.columns.get_loc(df.iloc[index].last_valid_index())+1:] =\
    [(df.iloc[index,m.columns.get_loc(df.iloc[index].last_valid_index()):][0]-(x+1)).astype(int) \
    for x in range((df.shape[1]-1)-df.columns.get_loc(df.iloc[index].last_valid_index()))] 

df[df < 0] = 0

這給了我想要的輸出

In [13]: df
Out[13]: 
    a   b   c   d   e   f   g   h   i   j
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN   2
1 NaN NaN NaN NaN  15  14  13  12  11  10
2   0   1   2   3   4   5   6   7   8   9
3   4   3   2   1   0   0   0   0   0   0

但。 在我的真實世界數據中,我有50K加列,並且上面的代碼花費WAAAY的時間太長。

有人可以建議我如何使運行速度更快嗎? 我相信解決方案將是以某種方式告訴代碼,一旦精算等於零,便移至下一行。 但是Idk怎么做,因為即使我使用max(0,subtract公式),代碼仍然會浪費時間。

謝謝。

我不知道它將有多快,但是您可以嘗試ffillfillnacumsum 例如:

>>> df
    a   b   c   d   e   f   g   h   i   j
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN   2
1 NaN NaN NaN NaN  15 NaN NaN NaN NaN NaN
2   0   1   2   3   4   5   6   7   8   9
3   4 NaN NaN NaN NaN NaN NaN NaN NaN NaN
>>> mask = df.ffill(axis=1).notnull() & df.isnull()
>>> df.where(~mask, df.fillna(-1).cumsum(axis=1).clip_lower(0))
    a   b   c   d   e   f   g   h   i  j
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN  2
1 NaN NaN NaN NaN  15  10   9   8   7  6
2   0   1   2   3   4   5   6   7   8  9
3   4   3   2   1   0   0   0   0   0  0

這有點棘手。 首先,我們通過向前填充最右邊的元素並查看其是否為null來確定需要填充哪些單元格(使用last_valid_index測試可能是一種更快的方法,但這是我首先想到的)

>>> mask = df.ffill(axis=1).notnull() & df.isnull()
>>> mask
       a      b      c      d      e      f      g      h      i      j
0  False  False  False  False  False  False  False  False  False  False
1  False  False  False  False  False   True   True   True   True   True
2  False  False  False  False  False  False  False  False  False  False
3  False   True   True   True   True   True   True   True   True   True

如果用-1填充空白點,則可以通過向右累積累加來獲得所需的值:

>>> (df.fillna(-1).cumsum(axis=1))
   a  b  c  d   e   f   g   h   i   j
0 -1 -2 -3 -4  -5  -6  -7  -8  -9  -7
1 -1 -2 -3 -4  11  10   9   8   7   6
2  0  1  3  6  10  15  21  28  36  45
3  4  3  2  1   0  -1  -2  -3  -4  -5

我們不需要許多這樣的值,但這沒關系,因為我們只插入需要的值。 但是,我們應該將其裁剪為0:

>>> df.fillna(-1).cumsum(axis=1).clip_lower(0)
   a  b  c  d   e   f   g   h   i   j
0  0  0  0  0   0   0   0   0   0   0
1  0  0  0  0  11  10   9   8   7   6
2  0  1  3  6  10  15  21  28  36  45
3  4  3  2  1   0   0   0   0   0   0

最后我們可以使用mask為False的原始值,以及mask為True的新值:

>>> df.where(~mask, df.fillna(-1).cumsum(axis=1).clip_lower(0))
    a   b   c   d   e   f   g   h   i  j
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN  2
1 NaN NaN NaN NaN  15  10   9   8   7  6
2   0   1   2   3   4   5   6   7   8  9
3   4   3   2   1   0   0   0   0   0  0

(注意:這假設我們需要填充的行看起來像示例中的行。如果它們比較雜亂,我們將不得不做更多的工作,但是將應用相同的技術。)

暫無
暫無

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

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