【问题标题】:Have only 1 record per date in a pandas dataframe熊猫数据框中每个日期只有 1 条记录
【发布时间】:2020-09-24 23:42:18
【问题描述】:

背景:在 mplfinance 中,我希望能够在同一个栏中绘制多个交易标记。目前据我了解,您只能将 1 个(或 1 个买入和 1 个卖出)添加到同一个柱中。除非我创建另一个系列,否则我不能在同一个柱的同一侧再进行 2 次交易。

这是一个例子:

d = {'TradeDate': ['2018-10-15 06:00:00',
                   '2018-10-29 03:00:00',
                   '2018-10-29 03:00:00',
                   '2018-10-29 06:00:00',
                   '2018-11-15 05:00:00',
                   '2018-11-15 05:00:00',
                   '2018-11-15 05:00:00'],
     'Price': [1.1596,
               1.1433,
               1.13926,
               1.14015,
               1.1413,
               1.1400,
               1.1403]}
df = pd.DataFrame(data=d)

df

    TradeDate           Price
0   2018-10-15 06:00:00 1.15960
1   2018-10-29 03:00:00 1.14330
2   2018-10-29 03:00:00 1.13926
3   2018-10-29 06:00:00 1.14015
4   2018-11-15 05:00:00 1.14130
5   2018-11-15 05:00:00 1.14000
6   2018-11-15 05:00:00 1.14030

如您所见,有 2 个日期时间的多笔交易。现在我想应用一条规则说“如果每个日期有超过 1 笔交易(此处:价格),请为额外价格创建一个新列,继续这样做,直到同一 TradeDate(日期时间)的所有价格都已跨列分布,并且所有日期时间都是唯一的”。因此,同一日期的价格越多,需要的额外列就越多。

最终结果是这样的(我手动整理了这些数据):

    TradeDate           Price   Price2  Price3
0   2018-10-15 06:00:00 1.15960 NaN     NaN
1   2018-10-29 03:00:00 1.14330 1.13926 NaN
3   2018-10-29 06:00:00 1.14015 NaN     NaN
4   2018-11-15 05:00:00 1.14130 1.14000 1.1403

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    诀窍是为每个唯一的日期时间添加一个增量计数器。这样,如果多次遇到日期时间,则此计数器会增加。

    为此,我们按交易日期分组,并获得给定交易日期重复交易日期数量的累积计数。然后我在这个值上加 1,这样我们的计数就从 0 的 1 开始。

    df["TradeDate_count"] = df.groupby("TradeDate").cumcount() + 1
    
    print(df)
                TradeDate    Price  TradeDate_count
    0 2018-10-15 06:00:00  1.15960                1
    1 2018-10-29 03:00:00  1.14330                1
    2 2018-10-29 03:00:00  1.13926                2
    3 2018-10-29 06:00:00  1.14015                1
    4 2018-11-15 05:00:00  1.14130                1
    5 2018-11-15 05:00:00  1.14000                2
    6 2018-11-15 05:00:00  1.14030                3
    

    现在我们已经添加了该列,我们可以简单地进行调整以实现您想要的结果。请注意,我添加了一个rename(...) 方法只是为了将“价格”添加到我们的列名中。我还使用了rename_axis 方法,因为我们的数据透视为我们返回了一些用户难以查看的列的命名索引,所以我认为最好将其删除。

    new_df = (df.pivot(index="TradeDate", columns="TradeDate_count", values="Price")
               .rename(columns="price{}".format)
               .rename_axis(columns=None))
    
                          price1   price2  price3
    TradeDate                                    
    2018-10-15 06:00:00  1.15960      NaN     NaN
    2018-10-29 03:00:00  1.14330  1.13926     NaN
    2018-10-29 06:00:00  1.14015      NaN     NaN
    2018-11-15 05:00:00  1.14130  1.14000  1.1403
    

    【讨论】:

    • 非常优雅,应该想到它,但我仍然在为所有不同但相似的方法(join、merge、pivot、groupby)而苦恼
    • 别担心,我已经在pandas 上花费了相当多的时间,所以大多数这些数据操作都是一种第二天性。但是,如果您还没有看过 pandas cheatsheet,我肯定会推荐它,它肯定有助于组织所有这些方法在 imo 上的作用。
    【解决方案2】:

    稍微不同的方法是按TradeDate 对数据进行分组,并将所有值连接到一个列表中。然后可以将其拉出到单独的列中并分配给新的数据框。

    reduce = df.groupby('TradeDate').agg(list)
    new_df = pd.DataFrame(reduced['Price'].to_list(), index=reduced.index)
    

    根据其他答案,如果您想重命名以便更好地理解,您可以执行以下操作:

    new_df.rename(columns=lambda x: f'Price{x if x > 0 else ""}', inplace=True)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2020-11-29
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 2021-10-21
      相关资源
      最近更新 更多