首页 > 解决方案 > 根据数据框中的目标日期输入正值和负值

问题描述

我有一个带有股票数据的 df,并且想在 target_date 之前和之后输入负整数和正整数(描述天数) - 如下所示:

我有什么(日期是索引):

date      symbol    open    high    low close   volume
12/9/1988   AAPL    1.4018  1.4107  1.3839  1.3975  11239200
12/12/1988  AAPL    1.4018  1.4107  1.375   1.375   29470000
12/13/1988  AAPL    1.375   1.3839  1.3661  1.3839  30637600
12/14/1988  AAPL    1.375   1.4286  1.375   1.4196  48325200
12/15/1988  AAPL    1.4286  1.4464  1.4018  1.4107  28142800
12/16/1988  AAPL    1.4107  1.4464  1.4018  1.4332  45872400
12/19/1988  AAPL    1.4375  1.4643  1.4286  1.4554  58581600
12/20/1988  AAPL    1.4643  1.4821  1.4511  1.4643  68546800
12/21/1988  AAPL    1.4643  1.5 1.4643  1.4911  60491200
12/22/1988  AAPL    1.4911  1.5 1.4554  1.4643  26507600
12/23/1988  AAPL    1.4643  1.4779  1.4643  1.4689  10239600
12/27/1988  AAPL    1.4643  1.4821  1.4464  1.4464  14996800
12/28/1988  AAPL    1.4464  1.4554  1.4196  1.4375  12885600

下面是我想要的目标日期为 12/16/1988 的表示:

  1. 创建一个名为“day”的列
  2. 在目标日期(例如,1988 年 12 月 16 日) - 在“天”列中输入“0”
  3. 在“天”列中 - 在目标日期之前输入 -1 到 -n(日期之前的 df 长度)
  4. 在“天”列中 - 在目标日期之后输入 1 到 n(日期之后的 df 长度)
date       day  symbol  open    high    low close   volume
12/9/1988   -5  AAPL    1.4018  1.4107  1.3839  1.3975  11239200
12/12/1988  -4  AAPL    1.4018  1.4107  1.375   1.375   29470000
12/13/1988  -3  AAPL    1.375   1.3839  1.3661  1.3839  30637600
12/14/1988  -2  AAPL    1.375   1.4286  1.375   1.4196  48325200
12/15/1988  -1  AAPL    1.4286  1.4464  1.4018  1.4107  28142800
12/16/1988  0   AAPL    1.4107  1.4464  1.4018  1.4332  45872400
12/19/1988  1   AAPL    1.4375  1.4643  1.4286  1.4554  58581600
12/20/1988  2   AAPL    1.4643  1.4821  1.4511  1.4643  68546800
12/21/1988  3   AAPL    1.4643  1.5 1.4643  1.4911  60491200
12/22/1988  4   AAPL    1.4911  1.5 1.4554  1.4643  26507600
12/23/1988  5   AAPL    1.4643  1.4779  1.4643  1.4689  10239600
12/27/1988  6   AAPL    1.4643  1.4821  1.4464  1.4464  14996800
12/28/1988  7   AAPL    1.4464  1.4554  1.4196  1.4375  12885600

我考虑采用以下方法(在 SO 上找到,但找不到源):

lenDF = (int(len(df) / 2))
df.insert(0, 'day', range(-lenDF, -lenDF + len(df)))

在目标日期之前的 df 长度可能与目标日期之后的不同之前,这并不完全适合我的目的。它与 target_date 的“day”列中的“0”不匹配。

我还尝试在目标日期之前和之后截断 df - 但与上述解决方案相同的问题 - 它与 target_date 的“day”列中的“0”不匹配。

df_before_target = df.truncate(before=target_date)
df_after_target = df.truncate(after=target_date)

len_b4 = len(df_before_target ) - 1  # substracting 1 to account for double counting of target_date in the truncated dfs.

len_a4 = len(df_after_target )
df.insert(0, 'day', range(-len_b4, -len_a4 + len(df)))

感谢您的任何帮助。

标签: pythonpython-3.xpandasdataframe

解决方案


我认为numpybusday_count()在这里会很好用。

我更喜欢在日期中使用ISO 8601表示法。你可以通过使用 pandas 的DatetimeIndex类来做到这一点:

df.index = pd.DatetimeIndex(df.index)

我们可以获取您所需列的数据,如下所示:

days = [np.busday_count('1988-12-16', x.date()) for x in df.index]

它遍历您中的每个pd.Timestamp对象,DatetimeIndex并计算与您的目标日期的差异(从工作日的角度)1988-12-16

然后您可以将此数据分配给您的数据框,如下所示:

df['day'] = days

并重新排序列,如您的帖子中所示:

df.reindex(columns=['day', 'symbol', 'open', 'high', 'low', 'close', 'volume'])

推荐阅读