【问题标题】:In Python Pandas , searching where there are 4 consecutive rows where values going up在 Python Pandas 中,搜索值上升的连续 4 行
【发布时间】:2021-11-12 12:08:15
【问题描述】:

我想弄清楚如何标记价格是 4 次加价的一部分的行。 “is_consecutive”实际上是标记。

我设法做到了行之间的差异:

df['diff1'] = df['Close'].diff()

但我没能找出哪一行是 4 次加价的一部分。

我想使用 df.rolling() 。

例子df,

在第 0-3 行,我们需要在 ["is_consecutive"] 列上获得 'True' 的输出,因为连续行上的 ['diff1'] 增加了 4 行。

在第 8-11 行,我们需要在 ["is_consecutive"] 列上获得 'False' 的输出,因为此连续行上的 ['diff1'] 为零。

   Date      Price           diff1    is_consecutive   
0  1/22/20    0               0          True
1  1/23/20    130            130         True
2  1/24/20    144            14          True
3  1/25/20    150            6           True
4  1/27/20    60            -90          False
5  1/28/20    95             35          False
6  1/29/20    100            5           False
7  1/30/20    50            -50          False
8  2/01/20    100            0           False
9  1/02/20    100            0           False
10  1/03/20   100            0           False
11  1/04/20   100            0           False
12  1/05/20   50            -50          False

一般例子:

如果 价格 = [30,55,60,65,25]

列表中连续数字的不同形式:

diff1 = [0,25,5,5,-40]

所以当 diff1 为加时,它实际上意味着连续价格上涨。

我需要标记(在 df 中)有 4 个连续上升的行。

感谢您的帮助 (-:

【问题讨论】:

标签: python pandas dataframe matplotlib diff


【解决方案1】:

尝试:.rolling,窗口大小为4,最小周期为1

df["is_consecutive"] = (
    df["Price"]
    .rolling(4, min_periods=1)
    .apply(lambda x: (x.diff().fillna(0) >= 0).all())
    .astype(bool)
)
print(df)

打印:

      Date  Price  is_consecutive
0  1/22/20      0            True
1  1/23/20    130            True
2  1/24/20    144            True
3  1/25/20    150            True
4  1/26/20     60           False
5  1/26/20     95           False
6  1/26/20    100           False
7  1/26/20     50           False

【讨论】:

  • 好一个安德烈 ;) +1
  • 嘿,谢谢,但它的计数连续价格也有相同的值,我试图更改为: (lambda x: (x.diff().fillna(0) >= 0.001) 但它没用,你能帮我吗?(-:
【解决方案2】:

假设数据框已排序。一种方法是根据差值的累积和来识别在 3 天的上涨趋势(即 4 天的上涨趋势)之后价格第一次上涨。

quant1 = (df['Price'].diff().apply(np.sign) == 1).cumsum()
quant2 = (df['Price'].diff().apply(np.sign) == 1).cumsum().where(~(df['Price'].diff().apply(np.sign) == 1)).ffill().fillna(0).astype(int)
df['is_consecutive'] = (quant1-quant2) >= 3

请注意,以上仅考虑严格增加的价格(不相等)。

然后我们使用 win_view 自定义函数覆盖前 3 个价格的 is_consecutive 标签也为 TRUE

def win_view(x, size):
    if isinstance(x, list):
        x = np.array(x)
    if isinstance(x, pd.core.series.Series):
        x = x.values
    if isinstance(x, np.ndarray):
        pass
    else:
        raise Exception('wrong type')
    return np.lib.stride_tricks.as_strided(
        x,
        shape=(x.size - size + 1, size),
        strides=(x.strides[0], x.strides[0])
    )


arr = win_view(df['is_consecutive'], 4)
arr[arr[:,3]] = True

请注意,我们将值替换为 True。

编辑 1 受自定义win_view函数的启发,我意识到可以通过win_view(无需使用cumsums)简单地获得它的解决方案如下:

df['is_consecutive'] = False
arr = win_view(df['Price'].diff(), 4)
arr_ind = win_view(list(df['Price'].index), 4)
mask = arr_ind[np.all(arr[:, 1:] > 0, axis=1)].flatten()
df.loc[mask, 'is_consecutive'] = True

我们维护 2 个数组,1 个用于返回,1 个用于索引。我们收集我们有 3 个连续正回报 np.all(arr[:, 1:] > 0, axis=1(即 4 个上涨价格)的指数,并替换我们原始 df 中的那些。

【讨论】:

  • 感谢您的回复 (-:
【解决方案3】:

该函数将返回名为 "consecutive_up" 的列,它代表属于 5 个增加系列的所有行,"consecutive_down" 代表属于 4 个法令系列的所有行。

def c_func(temp_df):

     temp_df['increase'] = temp_df['Price'] > temp_df['Price'].shift()
     temp_df['decrease'] = temp_df['Price'] < temp_df['Price'].shift()

     temp_df['consecutive_up'] = False
     temp_df['consecutive_down'] = False

     for ind, row in temp_df.iterrows():
          if row['increase'] == True:
               count += 1
          else:
               count = 0
          if count == 5:
               temp_df.iloc[ind - 5:ind + 1, 4] = True
          elif count > 5:
               temp_df.iloc[ind, 4] = True

     for ind, row in temp_df.iterrows():
          if row['decrease'] == True:
               count += 1
          else:
               count = 0
          if count == 4:
               temp_df.iloc[ind - 4:ind + 1, 5] = True
          elif count > 4:
               temp_df.iloc[ind, 5] = True
     return temp_df

【讨论】:

    猜你喜欢
    • 2019-10-25
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 2011-12-28
    相关资源
    最近更新 更多