gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 21:54:15 25 4
gpt4 key购买 nike

对于问题的措辞不佳,我深表歉意,但这是我能做的最好的。我确切地知道我想要什么,但不知道如何提出要求。

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

取值为 1 或 0 的两个条件会触发同样取值为 1 或 0 的信号。无论如何,条件 A 都会触发信号(如果 A = 1,则信号 = 1,否则信号 = 0)。条件 B 不触发信号,但如果条件 B 保持等于 1,信号将保持触发状态在先前由条件 A 触发信号之后。只有在 A 和 B 都回到 0 后,信号才回到 0。

<强>1。输入:

enter image description here

<强>2。期望的输出 (signal_d) 并确认 for 循环可以解决它 (signal_l):

enter image description here

<强>3。我尝试使用 numpy.where():

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() 这样的向量化函数来解决这个问题。而且我知道这对于更大的数据帧来说会快得多。

感谢您的任何建议!

最佳答案

我不认为有一种方法可以比 Python 循环更快地向量化此操作。 (至少,如果你只想坚持使用 Python、pandas 和 numpy,则不会。)

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

这是对您的脚本的修改,其中包含两个函数:add_signal_l(df)add_lagged(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 session 中运行的两个函数的时间比较:

In [85]: df
Out[85]:
condition_A condition_B signal_d
dates
2017-06-09 0 0 0
2017-06-10 0 1 0
2017-06-11 0 1 0
2017-06-12 0 1 0
2017-06-13 1 0 1
2017-06-14 1 0 1
2017-06-15 0 1 1
2017-06-16 0 1 1
2017-06-17 0 1 1
2017-06-18 0 1 1
2017-06-19 0 1 1
2017-06-20 1 0 1
2017-06-21 1 0 1
2017-06-22 0 0 0

In [86]: %timeit add_signal_l(df)
8.45 ms ± 177 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [87]: %timeit add_lagged(df)
137 µs ± 581 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

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

关于python - 如何矢量化使用其自身输出的滞后值的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44455481/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com