Python 如何在引用前几行时迭代数据帧?
我正在迭代Python数据帧,发现它非常慢。我知道在Pandas中,您试图对所有内容进行矢量化,但在本例中,我特别需要迭代(或者如果可以进行矢量化,我不清楚如何进行) 逻辑很简单:有两列“A”和“B”,以及一个结果列“信号”。如果A等于1,则将信号设置为1。如果B等于1,则将信号设置为0。否则,信号就和以前一样了。换句话说,A列是“开”信号,B列是“关”信号,“信号”表示状态 这是我的密码: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
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很抱歉听到你不能采用这个答案来解决你的问题。