【问题标题】:Avoiding loops in python/pandas避免 python/pandas 中的循环
【发布时间】:2021-11-25 19:28:01
【问题描述】:

我可以对基本的东西做 python/pandas,但我仍然在 pandas 的“不需要循环”世界中挣扎。我倾向于退回到转换为列表并像在 VBA 中那样执行循环,然后将这些列表带回 dfs。我知道有一个更简单的方法,但我想不通。

我的简单示例只是一个非常基本的策略,如果系列高于 70,则创建 -1 信号并保持 -1 直到信号变为 1 时系列跌破 30 并保持此信号直到值高于 70以此类推。

我可以通过简单的列表循环来做到这一点,但我知道这远非“Pythonic”!任何人都可以帮助将其“翻译”成一些没有循环的更好的代码吗?

#rsi_list is just a list from a df column of numbers. Simple example:
rsi={'rsi':[35, 45, 75, 56, 34, 29, 26, 34, 67. 78]}
rsi=pd.DataFrame(rsi)
rsi_list=rsi['rsi'].tolist()

signal_list=[]
hasShort=0
hasLong=0
for i in range(len(rsi_list)-1):           
    if rsi_list[i] >= 70 or hasShort==1:
        signal_list.append(-1)
    
        if rsi_list[i+1] >= 30:
            hasShort=1
        else:
            hasShort=0
    
    elif rsi_list[i] <= 30 or hasLong==1:
        signal_list.append(1)
        
        if rsi_list[i+1] <= 70:
            hasLong=1
        else:
            hasLong=0
    else:
        signal_list.append(0)

#last part just for the list to be the same lenght of the original df as I put it back as a column    
if rsi_list[-1]>=70:
    signal_list.append(-1)
else:
    signal_list.append(1)

【问题讨论】:

标签: pandas loops


【解决方案1】:

首先clip 将值下限为 30,上限为 70,使用where 将所有不是 30 或 70 的值更改为 nan。replace 通过 1 和 -1 传播这些值ffillfillna 前 30 或 70 之前的值为 0。

rsi['rsi_cut'] = (
    rsi['rsi'].clip(lower=30,upper=70)
       .where(lambda x: x.isin([30,70]))
       .replace({30:1, 70:-1})
       .ffill()
       .fillna(0)
)
print(rsi)
   rsi  rsi_cut
0   35      0.0
1   45      0.0
2   75     -1.0
3   56     -1.0
4   34     -1.0
5   29      1.0
6   26      1.0
7   34      1.0
8   67      1.0
9   78     -1.0

编辑:可能更简单一些,使用ge(大于或等于)和le(小于或等于)并进行减法,然后使用ffill 方法将replace 0s

print((rsi['rsi'].le(30).astype(int) - rsi['rsi'].gt(70))
       .replace(to_replace=0, method='ffill'))

【讨论】:

  • 太好了,谢谢!就像我希望的那样!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 2017-08-27
  • 2017-11-11
  • 2017-07-07
相关资源
最近更新 更多