簡體   English   中英

在數據框python上應用行明智的條件函數

[英]Apply row wise conditional function on dataframe python

我有一個數據框,我想在其中執行一個函數,該函數檢查實際值是否為相對最大值,並檢查先前的“n”值是否低於實際值。

有一個數據框“df_data”:

temp_list = [128.71, 130.2242, 131.0, 131.45, 129.69, 130.17, 132.63, 131.63, 131.0499, 131.74, 133.6116, 134.74, 135.99, 138.789, 137.34, 133.46, 132.43, 134.405, 128.31, 129.1]
df_data = pd.DataFrame(temp)

首先,我創建一個函數來檢查之前的條件:

def get_max(high, rolling_max, prev,post):
if ((high > prev) & (high>post) & (high>rolling_max)):
    return 1
else: 
    return 0
df_data['rolling_max'] = df_data.high.rolling(n).max().shift()

然后我按行應用先前的條件:

df_data['ismax'] = df_data.apply(lambda x: get_max(df_data['high'], df_data['rolling_max'],df_data['high'].shift(1),df_data['high'].shift(-1)),axis = 1)

問題是我總是收到以下錯誤:

ValueError:系列的真值不明確。 使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。

這是由於將 'get_max' 函數中的布爾條件應用於 Serie。

我很想擁有一個矢量化的函數,而不是使用循環。

嘗試:

df_data['ismax'] = ((df_data['high'].gt(df_data.high.rolling(n).max().shift())) & (df_data['high'].gt(df_data['high'].shift(1))) & (df_data['high'].gt(df_data['high'].shift(-1)))).astype(int)

發生錯誤是因為您將整個系列(整列)發送到 get_max 函數而不是按行發送。 為移動的“prev”和“post”值創建新列,然后使用df.apply(func, axis = 1)通常在這里可以正常工作。

正如您所暗示的,這個解決方案效率很低,隨着數據幀大小的增加,遍歷每一行會變得更慢。

在我的電腦上,下面的代碼發布:

  • LIST_MULTIPLIER = 1,矢量化代碼:0.29s,逐行代碼:0.38s
  • LIST_MULTIPLIER = 100,矢量化代碼:0.31s,逐行代碼 = 13.27s

通常,因此最好避免使用df.apply(..., axis = 1)因為您幾乎總是可以使用邏輯運算符獲得更好的解決方案。

import pandas as pd
from datetime import datetime

LIST_MULTIPLIER = 100
ITERATIONS = 100

def get_dataframe():
    temp_list = [128.71, 130.2242, 131.0, 131.45, 129.69, 130.17, 132.63, 
                 131.63, 131.0499, 131.74, 133.6116, 134.74, 135.99, 
                 138.789, 137.34, 133.46, 132.43, 134.405, 128.31, 129.1] * LIST_MULTIPLIER
    df = pd.DataFrame(temp_list)
    df.columns = ['high']
    return df

df_original = get_dataframe()

t1 = datetime.now()

for i in range(ITERATIONS):
    df = df_original.copy()
    df['rolling_max'] = df.high.rolling(2).max().shift()
    df['high_prev'] = df['high'].shift(1)
    df['high_post'] = df['high'].shift(-1)
    
    mask_prev = df['high'] > df['high_prev']
    mask_post = df['high'] > df['high_post']
    mask_rolling = df['high'] > df['rolling_max']
    
    mask_max = mask_prev & mask_post & mask_rolling
    
    df['ismax'] = 0
    df.loc[mask_max, 'ismax'] = 1
    
    
t2 = datetime.now()
print(f"{t2 - t1}")
df_first_method = df.copy()


t3 = datetime.now()

def get_max_rowwise(row):
    if ((row.high > row.high_prev) & 
        (row.high > row.high_post) & 
        (row.high > row.rolling_max)):
        return 1
    else: 
        return 0
    
for i in range(ITERATIONS):
    df = df_original.copy()
    df['rolling_max'] = df.high.rolling(2).max().shift()
    df['high_prev'] = df['high'].shift(1)
    df['high_post'] = df['high'].shift(-1)
    df['ismax'] = df.apply(get_max_rowwise, axis = 1)

t4 = datetime.now()
print(f"{t4 - t3}")
df_second_method = df.copy()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM