繁体   English   中英

如何在引用之前的行时遍历pandas数据框?

[英]How to iterate over a pandas dataframe while referencing previous rows?

我正在遍历一个Python数据框,发现它非常慢。 我了解在Pandas中您尝试对所有内容进行矢量化,但是在这种情况下,我特别需要进行迭代(或者如果可以进行矢量化,则不清楚如何执行此操作)。

逻辑很简单:您有两个列“ A”和“ B”,以及一个结果列“ signal”。 如果A等于1,则将signal设置为1。如果B等于1,则将signal设置为0。否则,signals与以前相同。 换句话说,列A是“开”信号,列B是“关”信号,并且“信号”表示状态。

这是我的代码:

def signals(indata):
    numrows = len(indata)
    data = pd.DataFrame(index= range(0,numrows))
    data['A'] = indata['A']
    data['B'] = indata['B']
    data['signal'] = 0


    for i in range(1,numrows):
        if data['A'].iloc[i] == 1:
            data['signal'].iloc[i] = 1
        elif data['B'].iloc[i] == 1:
            data['signal'].iloc[i] = 0
        else:
            data['signal'].iloc[i] = data['signal'].iloc[i-1]
    return data

输入/输出示例:

indata = pd.DataFrame(index = range(0,10))
indata['A'] = [0, 1, 0, 0, 0, 0, 1, 0, 0, 0]
indata['B'] = [1, 0, 0, 0, 1, 0, 0, 0, 1, 1]

signals(indata)

输出:

    A   B   signal
0   0   1   0
1   1   0   1
2   0   0   1
3   0   0   1
4   0   1   0
5   0   0   0
6   1   0   1
7   0   0   1
8   0   1   0
9   0   1   0

这种简单的逻辑使我的计算机需要46秒才能在具有随机生成的数据的2000行数据帧上运行。

df['signal'] = df.A.groupby((df.A != df.B).cumsum()).transform('head', 1)

df
   A  B  signal
0  0  1       0
1  1  0       1
2  0  0       1
3  0  0       1
4  0  1       0
5  0  0       0
6  1  0       1
7  0  0       1
8  0  1       0
9  0  1       0

这里的逻辑涉及根据AB之间的不等式将序列划分为组,每个组的值由A决定。

您完全不需要迭代就可以执行一些布尔索引

#set condition for A
indata.loc[indata.A == 1,'signal'] = 1
#set condition for B
indata.loc[indata.B == 1,'signal'] = 0
#forward fill NaN values
indata.signal.fillna(method='ffill',inplace=True)

解决我的问题的最简单答案是在遍历数据帧时不写入数据帧。 我在numpy中创建了一个零数组,然后在该数组中执行了迭代逻辑。 然后,将数组写入数据框的列中。

def signals3(indata):
    numrows = len(indata)
    data = pd.DataFrame(index= range(0,numrows))

    data['A'] = indata['A'] 
    data['B'] = indata['B']
    out_signal = np.zeros(numrows)

    for i in range(1,numrows):
        if data['A'].iloc[i] == 1:
            out_signal[i] = 1
        elif data['B'].iloc[i] == 1:
            out_signal[i] = 0
        else:
            out_signal[i] = out_signal[i-1]


    data['signal'] = out_signal

    return data

在2000行随机数据的数据帧上,这只需要43毫秒,而不是46秒(快1000倍)。

我还尝试了一个变体,在该变体中,我将数据帧的A列和B列分配给了系列,然后遍历该系列。 这有点快(27毫秒)。 但是看来,大多数的慢是写数据帧。

Coldspeed和djk的答案都比我的解决方案快(约4.5毫秒),但实际上,即使不是最佳选择,我也可能会迭代整个序列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM