Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.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 如何在引用前几行时迭代数据帧?_Python_Pandas_Dataframe_Iteration - Fatal编程技术网

Python 如何在引用前几行时迭代数据帧?

Python 如何在引用前几行时迭代数据帧?,python,pandas,dataframe,iteration,Python,Pandas,Dataframe,Iteration,我正在迭代Python数据帧,发现它非常慢。我知道在Pandas中,您试图对所有内容进行矢量化,但在本例中,我特别需要迭代(或者如果可以进行矢量化,我不清楚如何进行) 逻辑很简单:有两列“A”和“B”,以及一个结果列“信号”。如果A等于1,则将信号设置为1。如果B等于1,则将信号设置为0。否则,信号就和以前一样了。换句话说,A列是“开”信号,B列是“关”信号,“信号”表示状态 这是我的密码: def signals(indata): numrows = len(indata) d

我正在迭代Python数据帧,发现它非常慢。我知道在Pandas中,您试图对所有内容进行矢量化,但在本例中,我特别需要迭代(或者如果可以进行矢量化,我不清楚如何进行)

逻辑很简单:有两列“A”和“B”,以及一个结果列“信号”。如果A等于1,则将信号设置为1。如果B等于1,则将信号设置为0。否则,信号就和以前一样了。换句话说,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

这里的逻辑涉及到根据
A
B
之间的不相等性将序列划分为多个组,每个组的值由
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毫秒)。但似乎大部分的慢度都是在写入数据帧时出现的

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

coldspeed和djk的答案都比我的解决方案快(大约4.5ms),但实际上,我可能只是在系列中进行迭代,尽管这不是最优的。

观察pandas是如何处理这个逻辑门操作的很有趣,我仍然对这一点感到困惑。这真的很好,你能再解释一下它是如何工作的吗?这是一个有趣的解决方案,但对于更复杂的迭代,我自己无法提出这种逻辑。我真的只是在寻找一种简单、易于复制的方法来减少这类问题的处理时间。@karakumy很抱歉听到你不能采用这个答案来解决你的问题。