【问题标题】:How to add a new column by searching for data in a Pandas time series dataframe如何通过在 Pandas 时间序列数据框中搜索数据来添加新列
【发布时间】:2019-07-08 14:23:16
【问题描述】:

我有一个 Pandas 时间序列数据框。 它有 30 天的股票分钟数据。 我想创建一个新列,说明当天早上 6 点的股票价格,例如对于 1 月 1 日的所有行,我想要一个新列,其中包含 1 月 1 日中午的价格,对于 1 月 2 日的所有行,我想要一个新列,其中包含 1 月 2 日中午的价格,等等。

Existing timeframe:
Date   Time   Last_Price   Date   Time   12amT
1/1/19 08:00  100          1/1/19 08:00  ?
1/1/19 08:01  101          1/1/19 08:01  ?
1/1/19 08:02  100.50       1/1/19 08:02  ?
...
31/1/19 21:00 106         31/1/19 21:00  ?

我使用了这个 hack,但它很慢,我认为有一种更快更简单的方法来做到这一点。

for lab, row in df.iterrows() :
    t=row["Date"]
    df.loc[lab,"12amT"]=df[(df['Date']==t)&(df['Time']=="12:00")]["Last_Price"].values[0]

【问题讨论】:

  • 请显示想要的结果

标签: python pandas dataframe search


【解决方案1】:

一种方法是使用 groupby 和 pd.Grouper:

对于熊猫 24.1+

df.groupby(pd.Grouper(freq='D'))[0]\
  .transform(lambda x: x.loc[(x.index.hour == 12) & 
                             (x.index.minute==0)].to_numpy()[0])

大熊猫使用:

 df.groupby(pd.Grouper(freq='D'))[0]\
   .transform(lambda x: x.loc[(x.index.hour == 12) &
                              (x.index.minute==0)].values[0])

MVCE:

df = pd.DataFrame(np.arange(48*60), index=pd.date_range('02-01-2019',periods=(48*60), freq='T'))

df['12amT'] = df.groupby(pd.Grouper(freq='D'))[0].transform(lambda x: x.loc[(x.index.hour == 12)&(x.index.minute==0)].to_numpy()[0])

输出(头部):

                    0  12amT
2019-02-01 00:00:00  0    720
2019-02-01 00:01:00  1    720
2019-02-01 00:02:00  2    720
2019-02-01 00:03:00  3    720
2019-02-01 00:04:00  4    720

【讨论】:

  • 很好的答案斯科特!对于何时使用Grouper 而不是groupby,是否有经验法则?另外,transform 是否会自动拉伸标量值以适应原始 df 的索引?
  • @JoshFriedlander 我使用 groupby 和一个 pd.Grouper 对象每天按索引分组。 pd.Grouper(freq='D') 是我用于时间跨度分组的辅助对象。是的,变换返回输入列的相同长度。因此,我得到了一个标量值,并且 transform 正在使其“拉伸”到输入列的长度。假设您只想要每天的第一个值,那么您可以这样做,...transform(lambda x: x.iloc[0]) 它将返回该组中每条记录的第一个值。
  • 谢谢斯科特。请问你如何也得到接下来的 12am 的价格?
【解决方案2】:

我不知道为什么你有两个 DateTime 列,我做了我自己的例子来演示:

ind = pd.date_range('1/1/2019', '30/1/2019', freq='H')
df = pd.DataFrame({'Last_Price':np.random.random(len(ind)) + 100}, index=ind)

def noon_price(df):
    noon_price = df.loc[df.index.hour == 12, 'Last_Price'].values
    noon_price = noon_price[0] if len(noon_price) > 0 else np.nan
    df['noon_price'] = noon_price
    return df

df.groupby(df.index.day).apply(noon_price).reindex(ind)

reindex 默认情况下将使用其noon_price 填充每一天的行。

要添加具有次日中午价格的列,您可以shift该列向下24行,如下所示:

df['T+1'] = df.noon_price.shift(-24)

【讨论】:

  • 问没问题,这就是 SO 的用途!两件事 - 1)也许将此代码复制到顶部的问题中 2)您尝试过 Scott Boston 的解决方案吗?
  • 嗨,我也尝试了 Scott 的解决方案,但速度慢了很多。知道如何使用上面的代码来获得下一个工作日中午的价格吗?我应该创建一个新的 T+1 列然后使用它而不是 df.index.day 吗?这行得通吗?对不起,我是一个完全的初学者,你可能知道!
  • 嗨,Dan,我和 Scott 的解决方案都会为数据框中包含的每一天生成“中午价格” - 试试看!如果还有问题,请澄清。
  • 嗨,是的。它完美地工作,谢谢。是当天中午的价格。但是我也尝试添加一个 T+1 中午价格列,这是下一个工作日的中午价格。我似乎无法做到这一点。
  • 好的,我在底部添加了一行 - 试试看它是否有效!请注意,该月的最后一天会有空白 (NaN),因为那一天的信息是未来的。
猜你喜欢
  • 2020-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-11
  • 2019-02-24
  • 2016-02-01
  • 2018-12-06
相关资源
最近更新 更多