Python处理ASCII小时数据:宽表转长表及按日时排序问题
解决Pandas Melt后小时列排序异常的问题
嘿,我来帮你搞定这个问题!咱们一步步拆解你遇到的两个问题,重点解决排序的坑。
先回顾下你的场景
你的ASCII文件是制表符分隔的,第一列是日期ID(对应最终的day列),后面跟着24列以H1、H2...H24命名的小时数据,目标是转成day、hour、val的长表格式。
第一个问题:KeyError: 'day'
你已经通过指定sep='\t'解决了这个问题,本质是因为Pandas默认用逗号作为分隔符,而你的文件是制表符分隔的,导致读入时列识别错误,melt自然找不到day列。这里再补个小提醒:读文件时最好明确指定列名(如果文件第一行是列名的话),比如:
import pandas as pd # 读入文件,指定制表符分隔 df = pd.read_csv('your_data.txt', sep='\t') # 如果第一列的列名不是'day',记得重命名 df.rename(columns={'原日期列名': 'day'}, inplace=True)
重点问题:小时列按字典序排序(H1→H10→H2...)
这个坑是因为H1、H10这些是字符串类型,Pandas默认按字典序排序——简单说就是逐个字符比,H1的第二个字符是1,H10的第二个字符也是1,第三个字符是0,而H2的第二个字符是2,所以H10会排在H2前面。
有两种简单的解决方法:
方法1:提取小时数字,转整数后排序
先从hour列里提取出数字部分,转成整数,用这个整数列来排序,之后可以删掉它:
# 先执行melt转长表 melted_df = df.melt(id_vars=['day'], var_name='hour', value_name='val') # 提取小时的数字,转为整数 melted_df['hour_num'] = melted_df['hour'].str.extract('(\d+)').astype(int) # 按day和hour_num排序,然后删掉临时列 sorted_df = melted_df.sort_values(by=['day', 'hour_num']).drop(columns=['hour_num']) # 可选:重置索引 sorted_df = sorted_df.reset_index(drop=True)
方法2:用sort_values的key参数直接排序(Pandas 1.1.0+支持)
如果你不想加临时列,可以用key参数自定义排序规则,直接对hour列的数字部分排序:
melted_df = df.melt(id_vars=['day'], var_name='hour', value_name='val') # 直接排序,无需额外列 sorted_df = melted_df.sort_values( by=['day', 'hour'], key=lambda col: col.str.extract('(\d+)').astype(int) )
这样处理后,小时列就会按照H1→H2→...→H24的正确顺序排列啦!
内容的提问来源于stack exchange,提问作者Nat
相关产品推荐
相关产品推荐

