Pandas宽表转长表报错:float对象无len()方法,求解决
解决宽格式DataFrame转长格式及列名分割报错问题
嘿,我来帮你搞定这个宽转长的问题,顺便解释下你遇到的报错原因~
为什么你的列名分割代码会报错?
你用matches_df.columns.str.split('_', expand=True)时触发TypeError: object of type 'float' has no len(),核心原因是:你的DataFrame列名里混进了非字符串类型的元素(大概率是float类型的NaN)。
str.split()是字符串专属的方法,只能对字符串格式的列名操作。如果某个列名是float类型的NaN(不是字符串'NaN'),Python会直接报错——因为float类型没有str属性,也不能计算长度(len())。
正确的宽转长方法(完美匹配你的期望输出)
其实Pandas专门提供了melt()函数来做宽格式转长格式,比手动分割列名高效得多,还能避免列名类型的坑。以下是针对你示例数据的完整代码:
步骤1:构造示例数据(模拟你的输入)
import pandas as pd import numpy as np matches_df = pd.DataFrame({ 'index': [0, 1], 'S_1': [1, 1], 'S_2': [0, 1], 'S_3': [0, np.nan], 'S_4': [1, np.nan] }).set_index('index')
步骤2:执行宽转长操作
# 核心:用melt转长格式 long_df = matches_df.melt( ignore_index=False, # 保留原index列 var_name='num', # 原列名(S_1/S_2等)存入这个新列 value_name='S' # 原单元格数值存入这个新列 ) # 提取num列的数字部分(把S_1变成1) long_df['num'] = long_df['num'].str.split('_').str[1].astype(int) # 按index和num排序,让结果和你期望的完全一致 long_df = long_df.sort_values(['index', 'num']).reset_index(drop=False)
运行后得到的long_df就是你想要的输出:
| index | num | S |
|---|---|---|
| 0 | 1 | 1 |
| 0 | 2 | 0 |
| 0 | 3 | 0 |
| 0 | 4 | 1 |
| 1 | 1 | 1 |
| 1 | 2 | 1 |
| 1 | 3 | NaN |
| 1 | 4 | NaN |
处理额外列的情况
你提到还有其他列信息需要处理?没问题,只要在melt()里指定id_vars参数,把需要保留的列名放进去就行。比如原DataFrame有个group列需要保留:
示例代码:
# 假设有额外列的DataFrame matches_df_with_extra = pd.DataFrame({ 'index': [0, 1], 'group': ['A', 'B'], 'S_1': [1, 1], 'S_2': [0, 1], 'S_3': [0, np.nan], 'S_4': [1, np.nan] }).set_index('index') # 保留group列的同时转长格式 long_df_with_extra = matches_df_with_extra.melt( id_vars=['group'], # 指定要保留的额外列 ignore_index=False, var_name='num', value_name='S' ) # 同样处理num列 long_df_with_extra['num'] = long_df_with_extra['num'].str.split('_').str[1].astype(int)
这样就能在转长格式的同时,保留所有你需要的额外列啦~
内容的提问来源于stack exchange,提问作者oli5679
相关产品推荐
相关产品推荐

