【问题标题】:How can I create a new column on a Pandas Dataframe with conditions based on previous and next row?如何使用基于上一行和下一行的条件在 Pandas Dataframe 上创建新列?
【发布时间】:2020-09-04 21:44:51
【问题描述】:

我正在尝试创建一个新的 Pandas 列,用于指示与上面的行和下面的行相比,一个数字是否最大。

该列将是二进制的,其中“1”表示它是与最后一行和下一行相比的最大数字,“0”表示不满足条件。

这是数据的样子:

           Date      High
    0   2015-11-11  25.90
    1   2015-11-12  27.12
    2   2015-11-13  26.20
    3   2015-11-16  26.19
    4   2015-11-17  25.51
    5   2015-11-18  26.31
    6   2015-11-19  26.00
    7   2015-11-20  27.01
    8   2015-11-23  25.60
    9   2015-11-24  27.00
    10  2015-11-25  26.49

这是我想要的结果:

    Date        High    higher
0   2015-11-11  25.90   0.0
1   2015-11-12  27.12   1.0
2   2015-11-13  26.20   0.0
3   2015-11-16  26.19   0.0
4   2015-11-17  25.51   0.0
5   2015-11-18  26.31   1.0
6   2015-11-19  26.00   0.0
7   2015-11-20  27.01   1.0
8   2015-11-23  25.60   0.0
9   2015-11-24  27.00   1.0
10  2015-11-25  26.49   0.0

为了进一步说明,这是我在 Microsoft Excel 上所做的,这正是我试图用 Python 实现的: ExcelExample

第一次尝试:

for i in dftest['High']:
    if dftest['High'][i] > dftest['High'][i-1] and dftest['High'][i] > dftest['High'][i+1]:
        dftest['higher'] = 1
    else:
        dftest['higher'] = 0

这会导致错误: “TypeError:无法使用类‘float’的这些索引器[25.9]对类‘pandas.core.indexes.range.RangeIndex’进行标签索引”

第二次尝试: 这里我尝试使用'.shift()'。

for i in dftest['High']:
    if dftest['High'] > dftest['High'].shift(1) and dftest['High'] > dftest['High'].shift(-1):
        dftest['higher'] = 1
    else:
        dftest['higher'] = 0

这会导致错误: “TypeError: &: 'float' 和 'float' 不支持的操作数类型”

第三次尝试(类似于第二次尝试): 使用 '&' 运算符而不是 'and'。

导致错误: “TypeError:无法使用类‘float’的这些索引器[25.9]对类‘pandas.core.indexes.range.RangeIndex’进行标签索引”

将不胜感激任何形式的帮助!

编辑:如果我想找到 5 个或 7 个或 9 个连续数字中的最高值,如果提供的解决方案可以轻松交替,我将不胜感激。再次感谢!

【问题讨论】:

    标签: python python-3.x pandas dataframe conditional-statements


    【解决方案1】:

    您可以使用 .pct_change() 来查看值是增加还是减少,然后使用 np.where() 根据条件替换值。

    df = pd.read_clipboard()
    df['higher'] = df['High'].pct_change()
    df['higher'] = np.where(df['higher'] > 0, 1.0, 0.0)
    
    print(df)
    
    
        Date        High    higher
    0   2015-11-11  25.90   0.0
    1   2015-11-12  27.12   1.0
    2   2015-11-13  26.20   0.0
    3   2015-11-16  26.19   0.0
    4   2015-11-17  25.51   0.0
    5   2015-11-18  26.31   1.0
    6   2015-11-19  26.00   0.0
    7   2015-11-20  27.01   1.0
    8   2015-11-23  25.60   0.0
    9   2015-11-24  27.00   1.0
    10  2015-11-25  26.49   0.0
    

    对于您的评论,您可以进行最大滚动。

    df['rolling_max'] = df['High'].rolling(5, min_periods=1).max()
    
    print(df)
    
    Date    High    higher  rolling_max
    0   2015-11-11  25.90   0.0 25.90
    1   2015-11-12  27.12   0.0 27.12
    2   2015-11-13  26.20   0.0 27.12
    3   2015-11-16  26.19   0.0 27.12
    4   2015-11-17  25.51   0.0 27.12
    5   2015-11-18  26.31   1.0 27.12
    6   2015-11-19  26.00   0.0 26.31
    7   2015-11-20  27.01   1.0 27.01
    8   2015-11-23  25.60   0.0 27.01
    9   2015-11-24  27.00   1.0 27.01
    10  2015-11-25  26.49   1.0 27.01
    

    【讨论】:

    • 我编辑了我的回复以匹配您的示例列名称。
    • 非常感谢您的回复!如果我想找到 5 个(下面 2 个数字和上面 2 个数字)、7 个(下面 3 个数字和上面 3 个数字)或 9 个连续数字中的最大值,我该怎么做?
    • 滚动最大值是一个非常好的主意,但是在检查我的数据时,缺乏一致性。我已经发布了一个答案,非常感谢您查看它:)
    • “不一致”是什么意思? IIUC rolling().max() 专为您想要的而设计。您可能需要稍微调整一下参数以满足您的特定需求。但是,这篇文章现在有多个问题。我建议清理这个并提出一个新问题。
    【解决方案2】:

    这就是所谓的局部最大值

    from scipy.signal import argrelextrema
    ary=argrelextrema(df.High.values,np.greater)
    df['local max']=np.where(df.index.isin(ary[0]),1,0)
    df
              Date   High  local max
    0   2015-11-11  25.90          0
    1   2015-11-12  27.12          1
    2   2015-11-13  26.20          0
    3   2015-11-16  26.19          0
    4   2015-11-17  25.51          0
    5   2015-11-18  26.31          1
    6   2015-11-19  26.00          0
    7   2015-11-20  27.01          1
    8   2015-11-23  25.60          0
    9   2015-11-24  27.00          1
    10  2015-11-25  26.49          0
    

    【讨论】:

    • 非常感谢您的回复!如果我想找到 5 个(下面 2 个数字和上面 2 个数字)、7 个(下面 3 个数字和上面 3 个数字)或 9 个连续数字中的最大值,我该怎么做?
    • @Ibs 不同,你可能需要检查逻辑然后编写你自己的函数
    【解决方案3】:

    最后,我决定用这个:

    hf_three = []
    
    try:
        for i in df.index:   
            if df.loc[i]['High']>df.loc[i+1]['High'] and df.loc[i]['High']>df.loc[i-1]['High']:
                hf_three.append(1)
            else:
                hf_three.append(0)
    except ValueError:              # To handle cases where 'i-1' doesn't exist.
        hf_three.append(0)
    except KeyError:                # To handle cases where 'i+1' doesn't exist
        hf_three.append(0)
    
    df['higher'] = hf_three
    

    虽然这有效,但如果我将 '>' 替换为 '

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 2023-01-31
      • 1970-01-01
      相关资源
      最近更新 更多