Python 将数据帧函数转换为更高效的函数

Python 将数据帧函数转换为更高效的函数,python,pandas,numpy,vectorization,Python,Pandas,Numpy,Vectorization,给定以下两个数据帧 数据帧1 open high low close 0 340.649 340.829 340.374 340.511 1 340.454 340.843 340.442 340.843 2 340.521 340.751 340.241 340.474 3 340.197 340.698 340.145 340.420 4 340.332 340.609 340.123 340.128 5 340

给定以下两个数据帧

数据帧1

       open     high      low    close
0  340.649  340.829  340.374  340.511
1  340.454  340.843  340.442  340.843
2  340.521  340.751  340.241  340.474
3  340.197  340.698  340.145  340.420
4  340.332  340.609  340.123  340.128
5  340.092  340.462  339.993  340.207
6  340.179  340.437  339.810  339.983
7  340.296  340.498  339.977  340.036
8  340.461  340.641  340.189  340.367
9  340.404  340.820  340.338  340.589
数据帧2

       ohlc
0  0.374309
1  0.712707
2  0.791436
3  0.761050
4  0.779006
5  0.765193
6  0.578729
7  0.469613
8  0.385359
9  0.511050
下面的函数接受这两个数据帧并进行一些规范化和比较

def normalizeAndCompare(df1, df2):
    highest = df1["high"].max()
    lowest = df1["low"].min()

    df1["high"] = ((df1["high"] - lowest) / (highest - lowest))
    df1["low"] = ((df1["low"] - lowest) / (highest - lowest))
    df1["open"] = ((df1["open"] - lowest) / (highest - lowest))
    df1["close"] = ((df1["close"] - lowest) / (highest - lowest))
    df1["ohlc"] = (df1["open"] + df1["high"] + df1["low"] +df1["close"] ) / 4


    df1["highstd"] = df1["high"] + df1["ohlc"].rolling(window=10).std()
    df1["lowstd"] = df1["low"] - df1["ohlc"].rolling(window=10).std()

    df1["highpercent"] = df1["high"] + (df1["high"] * 0.05)
    df1["lowpercent"] = df1["low"] - (df1["low"] * 0.05)

    df1["highstd"] = df1['highstd'].fillna(value=df1['highpercent'])
    df1["lowstd"] = df1['lowstd'].fillna(value=df1['lowpercent'])

    result = (np.where(((df2["ohlc"] <= df1['highstd']) & (df2["ohlc"] >= df1['lowstd'])), 1, 0)).sum()

    return result
我的最终结果应该是pd_结果。
还有一点需要注意的是,dataframe1非常庞大,有几百万行。

这里有一个从一个主要是pandas函数到一个主要是numpy函数的相当快的转换(
rolling
仍在pandas中,但其余是numpy)。对于10000行,这大约快10倍

def norm_comp(df1, df2):

    open  = df1['open'].values
    high  = df1['high'].values
    low   = df1['low'].values
    close = df1['close'].values

    highest = high.max()
    lowest  = low.min()

    high  = ((high  - lowest) / (highest - lowest))
    low   = ((low   - lowest) / (highest - lowest))
    open  = ((open  - lowest) / (highest - lowest))
    close = ((close - lowest) / (highest - lowest))

    ohlc = (open + high + low + close) / 4

    roll_std = pd.Series(ohlc).rolling(10).std().values

    highstd = np.where( np.isnan(roll_std), high * 1.05, high + roll_std )
    lowstd  = np.where( np.isnan(roll_std), low  *  .95, low  - roll_std )

    return np.where(((df2.ohlc.values <= highstd) & 
                     (df2.ohlc.values >= lowstd)), 1, 0).sum()
以下是时间安排:

%timeit normalizeAndCompare(df1,df2)
100 loops, best of 3: 9.93 ms per loop

%timeit norm_comp(df1,df2)
1000 loops, best of 3: 957 µs per loop

这里有一个从pandas函数到numpy函数的快速转换(
rolling
仍在pandas中,但其余的是numpy)。对于10000行,这大约快10倍

def norm_comp(df1, df2):

    open  = df1['open'].values
    high  = df1['high'].values
    low   = df1['low'].values
    close = df1['close'].values

    highest = high.max()
    lowest  = low.min()

    high  = ((high  - lowest) / (highest - lowest))
    low   = ((low   - lowest) / (highest - lowest))
    open  = ((open  - lowest) / (highest - lowest))
    close = ((close - lowest) / (highest - lowest))

    ohlc = (open + high + low + close) / 4

    roll_std = pd.Series(ohlc).rolling(10).std().values

    highstd = np.where( np.isnan(roll_std), high * 1.05, high + roll_std )
    lowstd  = np.where( np.isnan(roll_std), low  *  .95, low  - roll_std )

    return np.where(((df2.ohlc.values <= highstd) & 
                     (df2.ohlc.values >= lowstd)), 1, 0).sum()
以下是时间安排:

%timeit normalizeAndCompare(df1,df2)
100 loops, best of 3: 9.93 ms per loop

%timeit norm_comp(df1,df2)
1000 loops, best of 3: 957 µs per loop

如果你需要测试效率和执行时间,我可以提供一个更大的dataframe1,你想标准化和比较连续的滑动/滚动窗口吗?是的@wwii,这正是我想要做的。但是我不知道如何在批处理大小为10的情况下优化它,
.rolling(window=10).std()
似乎没有意义。顺便说一句,我想你可能对熊猫中的循环和矢量化感到困惑。当您在pandas中执行类似于
df['high'].sum()
的操作时,这些操作已经矢量化了,您不需要再做任何操作。现在,在numpy中通常可以更快地完成任务,这仍然是事实,但这只是由于额外的开销。选择哪种方式取决于您是否想花额外的时间在numpy和快速可读的pandas代码中手动编写代码(在许多情况下仍然非常快).如果您需要测试效率和执行时间,我可以提供更大一点的dataframe1,以便对连续滑动/滚动窗口进行规范化和比较?是的@wwii,这正是我想要做的。但是我不知道如何在批处理大小为10的情况下优化它,
.rolling(window=10).std()
似乎没有意义。顺便说一句,我想你可能对熊猫中的循环和矢量化感到困惑。当您在pandas中执行类似于
df['high'].sum()
的操作时,这些操作已经矢量化了,您不需要再做任何操作。现在,在numpy中通常可以更快地完成任务,这仍然是事实,但这只是由于额外的开销。你要走哪条路取决于你是否想花更多的时间在numpy和快速可读的pandas代码中手动编写代码(在很多情况下仍然非常快)。谢谢你,确实时间要快得多。我得到的速度大约是原始函数的两倍。你说的“第二个函数”是什么意思?实际上只有一个我们可以直接在打开和关闭变量中包含df1['open']值和df1['close']值,然后在ohlc变量中直接包含打开和关闭,在roll_std变量中直接包含ohlc变量。通过这种方式,我们减少了额外的变量,并进一步提高了速度,唯一的缺点是它的可读性有点困难,没有问题。顺便说一句,我用
np.where
替换了
fillna
,这使它的速度加快了一点。我想这几乎就是从熊猫到裸体的所有低挂果实。np增加了很多:)谢谢,谢谢,时间确实快多了。我得到的速度大约是原始函数的两倍。你说的“第二个函数”是什么意思?实际上只有一个我们可以直接在打开和关闭变量中包含df1['open']值和df1['close']值,然后在ohlc变量中直接包含打开和关闭,在roll_std变量中直接包含ohlc变量。通过这种方式,我们减少了额外的变量,并进一步提高了速度,唯一的缺点是它的可读性有点困难,没有问题。顺便说一句,我用
np.where
替换了
fillna
,这使它的速度加快了一点。我想这几乎就是从熊猫到努比的所有低挂果实。np增加了很多:)谢谢