Python:如何在list / array / pd中设置零值。系列是下一个非零值?

时间:2016-02-29 17:40:15

标签: python algorithm python-2.7 sorting pandas

我有一个类似Python列表的结构,有超过100万个元素。每个元素都采用三个可能值中的一个,即-101。我想要实现的是用下一个非零值替换所有零。

例如,如果我有

[1, 0, 0, -1, 0, 1, 0, 0, 0, -1]

手术后我会

[1, -1 -1 ,-1, 1 ,1, -1 -1 -1 , - 1]。

我可以有一个嵌套的循环结构来实现这个目标,但是在列表中有超过100万个元素,它需要永远运行。有谁知道一个更快的算法来实现这个目标?

4 个答案:

答案 0 :(得分:4)

您可以先尝试创建Series,然后replace 0NaN,最后使用fillna

import pandas as pd
import numpy as np

li = [1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
s = pd.Series(li)
print s
0    1
1    0
2    0
3   -1
4    0
5    1
6    0
7    0
8    0
9   -1
dtype: int64


print s.replace({0:np.nan})
0     1
1   NaN
2   NaN
3    -1
4   NaN
5     1
6   NaN
7   NaN
8   NaN
9    -1
dtype: float64
print s.replace({0:np.nan}).fillna(method='bfill')
0    1
1   -1
2   -1
3   -1
4    1
5    1
6   -1
7   -1
8   -1
9   -1
dtype: float64

或者replace使用loc,然后按astype转换为int,最后使用tolist

s.loc[s == 0] = np.nan

s.loc[s == 0] = np.nan
print s.fillna(method='bfill').astype(int).tolist()
[1, -1, -1, -1, 1, 1, -1, -1, -1, -1]

答案 1 :(得分:1)

这是一个纯Python解决方案。

创建一个保留先前值状态的小类,并将当前值与此先前值进行比较。

class Checker:
    def _compare(self, val):
        if val or not self.prior:
            self.prior = val
            return val
        return self.prior
    def reverse_fill_list(self, some_list):
        self.prior = None
        return [self._compare(v) for v in some_list[::-1]][::-1]

然后以相反的顺序在列表中使用列表推导(使用[:: - 1]反转)。然后再次反转结果以恢复原始订单。

some_list = [1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
c = Checker()  # Instantiate object.

>>> c.reverse_fill_list(some_list)
[1, -1, -1, -1, 1, 1, -1, -1, -1, -1]


np.random.seed(0)
# Create one million values in range [-1, 0, 1].
a = np.random.random_integers(-1, 1, 1000000)
>>> a[:10]
array([-1,  0, -1,  0,  0,  1, -1,  1, -1, -1])

%timeit c.reverse_fill_list(a)
1 loops, best of 3: 311 ms per loop

使用Pandas(使用@Jezrael解决方案)的结果更快。

>>> pd.Series(a).replace({0:np.nan}).fillna(method='bfill').tolist()
10 loops, best of 3: 136 ms per loop

答案 2 :(得分:0)

你可以从最后开始迭代。这将是 O n )解决方案。

a=[0,1,0,0,0,0,-1,0];
length=len(a);
length=length-1;
//Assuming if last value is 0 you just let it be and the 0s before it.
val=0;
print a
for i in range(length):
    if (a[length-i] != 0):
        val=a[length -i];
    else:
        a[length-i]=val;
    i=i+1;
print a
exit();

答案 3 :(得分:0)

如果你想要纯Python,你可以使用一个简单的while循环:

li=[1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
i=len(li)-1
while i:
    if li[i]:
        val=li[i]
    else:
        li[i]=val
    i-=1    

>>> li
[1, -1, -1, -1, 1, 1, -1, -1, -1, -1] 

假设最后一个值是1或-1,但你没有指定最终值可能会欺骗你......