Python 在一个数据帧中,每个日期只有一条记录

Python 在一个数据帧中,每个日期只有一条记录,python,pandas,dataframe,Python,Pandas,Dataframe,背景:在mplfinance中,我希望能够在同一个酒吧中绘制多个交易标记。据我所知,目前你只能在同一个酒吧中添加1个(或1买1卖)。除非我创建另一个系列,否则我不能在同一个酒吧的同一边再进行两次交易 以下是一个例子: d = {'TradeDate': ['2018-10-15 06:00:00', '2018-10-29 03:00:00', '2018-10-29 03:00:00',

背景:在mplfinance中,我希望能够在同一个酒吧中绘制多个交易标记。据我所知,目前你只能在同一个酒吧中添加1个(或1买1卖)。除非我创建另一个系列,否则我不能在同一个酒吧的同一边再进行两次交易

以下是一个例子:

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

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

最终结果如下所示(我手动欺骗了这些数据):


诀窍是为每个唯一的datetime添加一个增量计数器。这样,如果多次遇到datetime,此计数器将增加

为此,我们按tradedate分组,并获得给定tradedate的重复tradedate数量的累积计数。然后我把1加到这个值上,这样我们的计数从1开始,而不是从0开始

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(…)
方法,只是为了在列名中添加“price”。我还使用了
rename\u axis
方法,因为我们的pivot为一些用户难以查看的列返回了一个命名索引,所以我认为最好删除它

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

一种稍有不同的方法是按
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)

非常优雅,应该已经想到了,但是我仍然在努力使用所有不同但相似的方法(join、merge、pivot、groupby),不用担心,我已经花了相当多的时间在
pandas
上,所以大多数这些数据操作都是第二天性。然而,如果你还没有看到它,我肯定会推荐它,它肯定有助于组织所有这些方法所做的事情。
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)