Pandas 时间序列数据帧中的逻辑元素操作

Pandas 时间序列数据帧中的逻辑元素操作,pandas,numpy,time-series,logical-operators,Pandas,Numpy,Time Series,Logical Operators,我有一个带有时间戳datetime索引和对应于每个日期的值的熊猫数据帧。例如,df=pd.DataFrame(['0.11','0.07','0.04','-0.11','-0.04','0.08','0.1'],索引=['2017-01-01','2017-01-02','2017-01-03','2017-01-04','2017-01-05','2017-01-06','2017-01-07'],列=['values']) 我想根据上述数据框的当前值和历史值创建一个附加列(我们称之为'ne

我有一个带有时间戳datetime索引和对应于每个日期的值的熊猫数据帧。例如,
df=pd.DataFrame(['0.11','0.07','0.04','-0.11','-0.04','0.08','0.1'],索引=['2017-01-01','2017-01-02','2017-01-03','2017-01-04','2017-01-05','2017-01-06','2017-01-07'],列=['values'])

我想根据上述数据框的当前值和历史值创建一个附加列(我们称之为
'new_value'

逻辑应该是:

  • 如果值大于或等于0.1,则应设置“新值” 到-1
  • 一旦“new_value”设置为-1,它应保持为-1,直到出现一个值 小于或等于0.05是注册的
  • 如果值小于或等于-0.1,则应设置“新值” 到+1
  • 一旦“new_value”设置为+1,它应该保持+1直到一个值 大于或等于-0.05是注册的
  • 否则,“新_值”等于0
  • 我尝试了多种解决方案,但似乎无法解决这个问题。例如:

    new_frame = pd.DataFrame(np.zeros(len(df.index),index=df.index,columns=['new_value'])
    for date in df.index:
        if df['value'][date.strftime('%Y-%m-%d')] > 0.1:
            new_frame.set_value(date.strftime("%Y-%m-%d"),'new_value',-1)
    
    但是我收到了错误:
    'ValueError:序列的真值是不明确的。使用a.empty、a.bool()、a.item()、a.any()或a.all()。

    如果我将第三行更改为:

    if df['value'][date.strftime('%Y-%m-%d').item() > 0.1:
    
    我收到错误:
    “ValueError:只能将大小为1的数组转换为Python标量”

    它的工作原理

    • 只需要获得一系列浮点数,将其命名为
      s
    • 设置左侧断点
      al
    • 设置左侧映射值
      bl
    • 设置右侧断点
      ar
    • 设置右侧映射值
      br
    • searchsorted
      将查找值应放在前面的索引
    • 使用
      searchsorted
      中的索引识别映射值
    • 在查找右侧值时,我使用
      side='right'
    • 再次映射值
    • 添加左侧和右侧结果
      nan
      +值将为
      nan
    • ffill
      向前传播值

    设置
    假设OP给出的数据帧
    df


    这是一个很好的答案,谢谢。就建立我的理解而言,有人能解释为什么我最初的方法不起作用吗?@Panda_User see如果有帮助的话,请随意投票:-)@Panda_User我知道你在最初阶段就被卡住了。。。是的,我给你的是矢量化的解决方案。你正在走使用循环的道路。现在你不必了。许多人在执行循环时会陷入将序列作为布尔值进行计算的陷阱。
    s = df['values'].astype(float)
    al = np.array([-.1, -.05])
    bl = np.array([1, np.nan, 0])
    ar = np.array([.05, .1])
    br = np.array([0, np.nan, -1])
    l = bl[al.searchsorted(s.values)]
    r = br[ar.searchsorted(s.values, side='right')]
    
    df.assign(new_values=pd.Series(l + r, s.index).ffill())
    
               values  new_values
    2017-01-01   0.11        -1.0
    2017-01-02   0.07        -1.0
    2017-01-03   0.04         0.0
    2017-01-04  -0.11         1.0
    2017-01-05  -0.04         0.0
    2017-01-06   0.08         0.0
    2017-01-07    0.1        -1.0
    
    df = pd.DataFrame(
        ['0.11', '0.07', '0.04', '-0.11',
         '-0.04', '0.08', '0.1'],
        ['2017-01-01', '2017-01-02',
         '2017-01-03', '2017-01-04',
         '2017-01-05', '2017-01-06',
         '2017-01-07'],
        ['values']
    )
    
               values
    2017-01-01   0.11
    2017-01-02   0.07
    2017-01-03   0.04
    2017-01-04  -0.11
    2017-01-05  -0.04
    2017-01-06   0.08
    2017-01-07    0.1