【问题标题】:Pandas dataframe iterate over rows without for loopsPandas 数据框在没有 for 循环的情况下遍历行
【发布时间】:2018-08-05 21:02:38
【问题描述】:

我有一个大约 300 万行的数据框,如下所示:

   date        size  price
0  2018-08-01  100   220
1  2018-08-01  110   245
2  2018-08-01  125   250
3  2018-08-02  110   210
4  2018-08-02  120   230
5  2018-08-02  150   260
6  2018-08-03  115   200

对于每一行,它是一个项目的交易。我们有商品的交易日期、尺寸和价格。

现在我想添加一个名为 avg_price 的列,这样每行交易的 avg_price 是 最后一天的 k 个交易的平均值与这个最接近的尺寸(非常类似于 k 最近邻居的想法)。

例如,当 k = 2 时,上面最后一行的 avg_price 应为 (210+230)/2=220,因为最接近的 2 个交易的大小为 110 和 120,对应的价格为 210 和 230。

预期的输出应该是:

   date        size  price avg_price
0  2018-08-01  100   220   NA
1  2018-08-01  110   245   NA
2  2018-08-01  125   250   NA
3  2018-08-02  110   210   (220+245)/2
4  2018-08-02  120   230   (245+250)/2
5  2018-08-02  150   260   (245+250)/2
6  2018-08-03  115   200   (210+230)/2

我写了一个 for 循环来遍历每一行,首先挑出最后一天的所有交易,然后按大小差异排序并计算前 k 个项目的平均值。但是,正如预期的那样,这是非常缓慢的。谁能指出一种更“矢量化”的方法?谢谢。

更新:每天的交易数量不固定,大约在 300 左右。

【问题讨论】:

  • 既然有两个110,为什么最后一行不是210+245
  • @RafaelC 其他 110 不是在 8/2 的前一天是 8/1。 2018 年 8 月 2 日最接近 115 的值是 110 和 120(210 和 230)
  • @RafaelC 因为我们只计算最后一天的平均值。
  • 你有固定的天数吗?例如,是否总是每个日期 3 行?
  • @RafaelC 不幸的是没有。每天有大约 300 行。

标签: python pandas dataframe


【解决方案1】:

我调用了dfa 原始数据框。首先在dfb 中创建您需要的数据,以便以后使用merge_asof

k = 2 # should work for any number
dfb = dfa.copy()
dfb = dfb.sort_values(['date','size']) #actually need in dfa too
# get the k-mean
dfb['avg_price'] = dfb.groupby('date').price.rolling(k).mean().values
#to look for the k nearest sizes in merge_asof
dfb['size'] = dfb.groupby('date')['size'].rolling(k).mean().values
# add one business day to shift all the date 
dfb['date'] = dfb['date'] + pd.tseries.offsets.BDay() 
dfb = dfb.dropna().drop('price',1)
dfb['size'] = dfb['size'].astype(int) #needed for the merge_asof
print (dfb)

        date   size  avg_price
1 2018-08-02    105      232.5
2 2018-08-02    117      247.5
4 2018-08-03    115      220.0
5 2018-08-03    135      245.0

您可以使用merge_asofdatenearest size(使用该方法需要sort_values):

dfa = (pd.merge_asof(dfa.sort_values('size'), dfb.sort_values('size'), 
                     on='size',by='date',direction='nearest')
         .sort_values(['date','size']).reset_index(drop=True))

结果是dfa:

        date  price  size  avg_price
0 2018-08-01    220   100        NaN
1 2018-08-01    245   110        NaN
2 2018-08-01    250   125        NaN
3 2018-08-02    210   110      232.5
4 2018-08-02    230   120      247.5
5 2018-08-02    260   150      247.5
6 2018-08-03    200   115      220.0

【讨论】:

    【解决方案2】:

    我不确定您的预期输出是什么,但如果您想在有多个交易的日期上找到最接近大小的平均值,您可以执行类似的操作。如果您正在寻找其他东西,请提供预期的输出:

    df = pd.read_clipboard()
    
    # find the diff on the size column and backfill the NaN values
    df['diff'] = df.groupby('date')['size'].diff().fillna(method='bfill')
    
    # group by date and use the lambda function to find the min diff
    df2 = df.groupby(['date']).apply(lambda x: x[x['diff'] == x['diff'].min()])
    
    # find the mean of price
    df2.groupby('date')['price'].mean()
    
    date
    2018-08-01    232.5
    2018-08-02    220.0
    Name: price, dtype: float64
    

    【讨论】:

      猜你喜欢
      • 2022-01-20
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      • 2018-03-24
      • 1970-01-01
      • 2019-07-02
      • 1970-01-01
      • 2020-03-01
      相关资源
      最近更新 更多