如何将使用自身输出滞后值的函数矢量化?

2024-04-25 03:41:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我很抱歉这个问题措辞不好,但我已经尽力了。 我知道我想要什么,但不知道该怎么要求。在

下面是一个例子所展示的逻辑:

值为1或0的两个条件触发信号,该信号也采用值1或0。条件A触发信号(如果A=1则信号=1,否则信号=0)。条件B不触发信号,但如果条件B保持等于1,则信号保持触发状态 在之前的信号被条件A触发后。 只有在A和B都回到0后,信号才回到0。在

1。输入:

enter image description here

2。期望输出(信号_d)以及确认for循环可以解决它(signal_l):

enter image description here

3。我尝试使用纽比。在哪里():

enter image description here

4。可复制片段:

    # Settings
    import numpy as np
    import pandas as pd
    import datetime

    # Data frame with input and desired output i column signal_d
    df = pd.DataFrame({'condition_A':list('00001100000110'),
                       'condition_B':list('01110011111000'),
                       'signal_d':list('00001111111110')})

    colnames = list(df)
    df[colnames] = df[colnames].apply(pd.to_numeric)
    datelist = pd.date_range(pd.datetime.today().strftime('%Y-%m-%d'), periods=14).tolist()
    df['dates'] = datelist
    df = df.set_index(['dates']) 

    # Solution using a for loop with nested ifs in column signal_l
    df['signal_l'] = df['condition_A'].copy(deep = True)
    i=0
    for observations in df['signal_l']:
        if df.ix[i,'condition_A'] == 1:
            df.ix[i,'signal_l'] = 1
        else:
            # Signal previously triggered by condition_A
            # AND kept "alive" by condition_B:                
            if df.ix[i - 1,'signal_l'] & df.ix[i,'condition_B'] == 1:
                 df.ix[i,'signal_l'] = 1
            else:
                df.ix[i,'signal_l'] = 0          
        i = i + 1



    # My attempt with np.where in column signal_v1
    df['Signal_v1'] = df['condition_A'].copy()
    df['Signal_v1'] = np.where(df.condition_A == 1, 1, np.where( (df.shift(1).Signal_v1 == 1) & (df.condition_B == 1), 1, 0))

    print(df)

使用带有滞后值和嵌套if语句的for循环是非常直接的,但是我不能使用像numpy.where()这样的向量化函数来解决这个问题。我知道这对于更大的数据帧来说会快得多。在

谢谢你的建议!在


Tags: importdfforsignal信号withnpwhere
1条回答
网友
1楼 · 发布于 2024-04-25 03:41:35

我不认为有一种方法可以比Python循环更快地将这个操作矢量化。(至少,如果你只想和Python、熊猫和纽比呆在一起的话,那就不会了。)

但是,可以通过简化代码来提高此操作的性能。您的实现使用if语句和大量的数据帧索引。这些都是相对昂贵的操作。在

下面是对脚本的修改,它包含两个函数:add_signal_l(df)和{}。第一个是你的代码,只是封装在一个函数中。第二种方法使用一个更简单的函数来实现同样的结果,它仍然是一个Python循环,但是它使用numpy数组和位运算符。在

import numpy as np
import pandas as pd
import datetime

#                                   -
# Create the test DataFrame

# Data frame with input and desired output i column signal_d
df = pd.DataFrame({'condition_A':list('00001100000110'),
                   'condition_B':list('01110011111000'),
                   'signal_d':list('00001111111110')})

colnames = list(df)
df[colnames] = df[colnames].apply(pd.to_numeric)
datelist = pd.date_range(pd.datetime.today().strftime('%Y-%m-%d'), periods=14).tolist()
df['dates'] = datelist
df = df.set_index(['dates']) 
#                                   -

def add_signal_l(df):
    # Solution using a for loop with nested ifs in column signal_l
    df['signal_l'] = df['condition_A'].copy(deep = True)
    i=0
    for observations in df['signal_l']:
        if df.ix[i,'condition_A'] == 1:
            df.ix[i,'signal_l'] = 1
        else:
            # Signal previously triggered by condition_A
            # AND kept "alive" by condition_B:                
            if df.ix[i - 1,'signal_l'] & df.ix[i,'condition_B'] == 1:
                 df.ix[i,'signal_l'] = 1
            else:
                df.ix[i,'signal_l'] = 0          
        i = i + 1

def compute_lagged_signal(a, b):
    x = np.empty_like(a)
    x[0] = a[0]
    for i in range(1, len(a)):
        x[i] = a[i] | (x[i-1] & b[i])
    return x

def add_lagged(df):
    df['lagged'] = compute_lagged_signal(df['condition_A'].values, df['condition_B'].values)

以下是在IPython会话中运行的两个函数的计时比较:

^{pr2}$

如您所见,add_lagged(df)要快得多。在

相关问题 更多 >