【问题标题】:Trying to create a new dataframe column in pandas based on a dataframe related if statement尝试根据与数据框相关的 if 语句在 pandas 中创建新的数据框列
【发布时间】:2017-04-17 16:53:31
【问题描述】:

我正在学习 Python 和 pandas,并练习不同的股票计算。我已尝试搜索有关此问题的帮助,但没有找到足够相似的响应,或者不明白如何根据之前的响应推断出正确的方法。

我已使用 datareader 将给定时间范围内的股票数据读取到数据帧 df 中。在 df 我有 Date Volume 和 Adj Close 列,我想用它们来根据给定的标准创建一个新列“OBV”。 OBV 是一个累积值,根据调整后的收盘价将今天的交易量值加上或减去前一天的 OBV。

OBV的计算很简单:

如果今天的调整收盘价高于昨天的调整收盘价,则将今天的交易量与昨天的(累计)交易量相加。

如果今天的调整收盘价低于昨天的调整收盘价,则从昨天的(累计)交易量中减去今天的交易量。

在第 1 天,OBV = 0

然后在时间范围内重复此操作并累积 OBV。

这是基本的导入并开始

import numpy as np
import pandas as pd
import pandas_datareader

import datetime
from pandas_datareader import data, wb

start = datetime.date(2012, 4, 16)
end = datetime.date(2017, 4, 13)

# Reading in Yahoo Finance data with DataReader
df = data.DataReader('GOOG', 'yahoo', start, end)

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

#This is what I cannot get to work, and I've tried two different ways.

#ATTEMPT1

def obv1(column):
    if column["Adj Close"] > column["Adj close"].shift(-1):
        val = column["Volume"].shift(-1) + column["Volume"]
    else:
        val = column["Volume"].shift(-1) - column["Volume"] 
    return val

df["OBV"] = df.apply(obv1, axis=1)

#ATTEMPT 2

def obv1(df):
    if df["Adj Close"] > df["Adj close"].shift(-1):
        val = df["Volume"].shift(-1) + df["Volume"]
    else:
        val = df["Volume"].shift(-1) - df["Volume"] 
    return val

df["OBV"] = df.apply(obv1, axis=1)

两者都给我一个错误。

【问题讨论】:

  • 如果当天的 AdjClose 没有变化会怎样?
  • 这是非常罕见的,因为在雅虎的数据中价格被评估到小数点后六位,但理论上,当然是实践。对于大多数 OBV,我的理解是,如果今天的调整收盘价高于或等于昨天的调整收盘价,则将今天的交易量添加到昨天的(累积)交易量。

标签: python function pandas dataframe


【解决方案1】:

考虑数据框df

np.random.seed([3,1415])
df = pd.DataFrame(dict(
        Volume=np.random.randint(100, 200, 10),
        AdjClose=np.random.rand(10)
    ))

print(df)

   AdjClose  Volume
0  0.951710     111
1  0.346711     198
2  0.289758     174
3  0.662151     190
4  0.171633     115
5  0.018571     155
6  0.182415     113
7  0.332961     111
8  0.150202     113
9  0.810506     126

当AdjClose 的变化为负时,将Volume 乘以-1。然后cumsum

(df.Volume * (~df.AdjClose.diff().le(0) * 2 - 1)).cumsum()

0    111
1    -87
2   -261
3    -71
4   -186
5   -341
6   -228
7   -117
8   -230
9   -104
dtype: int64

将此与df 的其余部分放在一起

df.assign(new=(df.Volume * (~df.AdjClose.diff().le(0) * 2 - 1)).cumsum())

   AdjClose  Volume  new
0  0.951710     111  111
1  0.346711     198  -87
2  0.289758     174 -261
3  0.662151     190  -71
4  0.171633     115 -186
5  0.018571     155 -341
6  0.182415     113 -228
7  0.332961     111 -117
8  0.150202     113 -230
9  0.810506     126 -104

【讨论】:

  • 谢谢!这行得通。为了实现这一点,我不得不稍微调整雅虎的数据,但这帮助我实现了这一目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 2020-10-25
  • 2022-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多