Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在数据帧中迭代行减去1_Python_Pandas - Fatal编程技术网

Python 在数据帧中迭代行减去1

Python 在数据帧中迭代行减去1,python,pandas,Python,Pandas,我有一个数据帧,我想从最后一个非空值开始迭代,然后从该值中减去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],\ '

我有一个数据帧,我想从最后一个非空值开始迭代,然后从该值中减去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等

通过执行以下操作,我达到了预期的输出

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
但是。在我的现实世界数据中,我有50K多个列,上面的代码花费的时间太长了

有人能建议我如何让这跑得更快吗? 我相信解决办法是告诉代码,一旦子动作等于零,就转到下一行。但Idk如何做到这一点,因为即使我使用max(0,减法公式),代码仍然会浪费时间进行减法运算


谢谢。

我不知道它的速度有多快,但您可以尝试使用
ffill
fillna
cumsum
。例如:

>>> 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测试可能有一种更快的方法,但这是我想到的第一件事)

如果我们用-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
最后,我们可以使用掩码为False的原始值,以及掩码为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

(注意:这假设我们需要填充的行与您的示例中的行相似。如果它们更混乱,我们需要做更多的工作,但同样的技术也适用。)

我不知道它会有多快,但您可以尝试使用
ffill
fillna
cumsum
。例如:

>>> 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测试可能有一种更快的方法,但这是我想到的第一件事)

如果我们用-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
最后,我们可以使用掩码为False的原始值,以及掩码为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
(注意:这假设我们需要填充的行与示例中的行相似。如果它们更混乱,我们需要做更多的工作,但同样的技术也适用。)