如何调整透视后Pandas DataFrame列顺序,按时间分组排列字段
如何调整Pandas透视表的列顺序,让每个时间对应的字段相邻排列?
问题描述
我正在使用以下Pandas代码:
import pandas as pd data = [['01/07/2020', '21:30', 3176.5, 3195, 3176.5, 3192, 21116], ['01/07/2020', '22:00', 3192.25, 3193.25, 3184, 3192, 13472], ['01/07/2020', '22:30', 3192.25, 3193, 3188.25, 3192.75, 6104], ['01/07/2020', '23:00', 3192.75, 3194.5, 3190.75, 3191.25, 2704], ['01/07/2020', '23:30', 3191, 3191.5, 3188.75, 3189, 1663]] # Create a DataFrame from the data list df = pd.DataFrame(data, columns=['Date', 'Time', 'Open', 'High', 'Low', 'Close', 'Volume']) # Pivot the DataFrame pivoted_df = df.pivot(index='Date', columns='Time', values=['Open', 'High', 'Low', 'Close', 'Volume']) print(pivoted_df)
当前代码输出如下:
Open High Low Close Volume Time 21:30 22:00 22:30 23:00 23:30 21:30 22:00 22:30 23:00 23:30 21:30 22:00 22:30 23:00 23:30 21:30 22:00 22:30 23:00 23:30 21:30 22:00 22:30 23:00 23:30 Date 01/07/2020 3176.5 3192.25 3192.25 3192.75 3191.0 3195.0 3193.25 3193.0 3194.5 3191.5 3176.5 3184.0 3188.25 3190.75 3188.75 3192.0 3192.0 3192.75 3191.25 3189.0 21116.0 13472.0 6104.0 2704.0 1663.0
我希望将每个Time对应的Open、High、Low、Close(注:原文Last应为Close)、Volume列相邻排列,得到如下期望输出:
Date 21:30 Open 21:30 High 21:30 Low 21:30 Last 21:30 Volume 22:00 Open 22:00 High 22:00 Low ... 23:00 High 23:00 Low 23:00 Last 23:00 Volume 23:30 Open 23:30 High 23:30 Low 23:30 Last 23:30 Volume 0 01/07/2020 3176.5 3195.0 3176.5 3192.0 21116.0 3192.25 3193.25 3184.0 ... 3194.5 3190.75 3191.25 2704.0 3191.0 3191.5 3188.75 3189.0 1663.0
请问是否可以实现这种列顺序调整?
解决方案
当然可以实现。你当前的透视表生成的是多层列索引(第一层为字段名,第二层为时间),只需调整列层级顺序、排序并合并列名即可达到目标:
完整代码实现
import pandas as pd data = [['01/07/2020', '21:30', 3176.5, 3195, 3176.5, 3192, 21116], ['01/07/2020', '22:00', 3192.25, 3193.25, 3184, 3192, 13472], ['01/07/2020', '22:30', 3192.25, 3193, 3188.25, 3192.75, 6104], ['01/07/2020', '23:00', 3192.75, 3194.5, 3190.75, 3191.25, 2704], ['01/07/2020', '23:30', 3191, 3191.5, 3188.75, 3189, 1663]] df = pd.DataFrame(data, columns=['Date', 'Time', 'Open', 'High', 'Low', 'Close', 'Volume']) # 生成透视表 pivoted_df = df.pivot(index='Date', columns='Time', values=['Open', 'High', 'Low', 'Close', 'Volume']) # 1. 交换列层级:将(字段, 时间)转为(时间, 字段) pivoted_df = pivoted_df.swaplevel(axis=1) # 2. 按时间+指定字段顺序排序列,确保每个时间下的字段顺序为Open/High/Low/Close/Volume field_order = ['Open', 'High', 'Low', 'Close', 'Volume'] pivoted_df = pivoted_df.sort_index( axis=1, level=[0, 1], key=lambda x: x.map(lambda y: field_order.index(y) if y in field_order else float('inf')) ) # 3. 合并列名,格式改为"时间 字段",同时替换Close为Last匹配期望输出 pivoted_df.columns = [' '.join(col).replace('Close', 'Last') for col in pivoted_df.columns] # 4. 重置索引,将Date从索引转为普通列 result_df = pivoted_df.reset_index() print(result_df)
关键步骤说明
- 交换列层级:通过
swaplevel(axis=1)把原来的列层级从[字段, 时间]翻转成[时间, 字段],让同一时间的字段自动归为一组。 - 指定字段顺序排序:用
sort_index配合自定义key,确保每个时间下的字段严格按照Open→High→Low→Close→Volume的顺序排列。 - 合并列名:将多层列索引的两个层级拼接成一个字符串,同时把
Close替换为Last以匹配你的期望输出格式。 - 重置索引:把
Date从行索引转换为普通列,和期望输出的结构完全一致。
内容的提问来源于stack exchange,提问作者NoLimitLondon
相关产品推荐
相关产品推荐

