如何用Pandas实现指定DataFrame转换并解决空结果问题?
Pandas DataFrame 转换问题:空DataFrame原因及解决方案
问题描述
我正尝试用Pandas处理Excel表格的DataFrame转换,需求步骤如下:
- 选取每个数据块的前4行 + 最后2行
- 堆叠所有数据块
- 删除最后3个未命名列
- 选择A列和E列
- 向下填充A列
- 创建包含序列值(ID-01至ID-06)的新列N1
- 创建新列N2,拼接数据块的首个值及其编号
但我写的代码返回了一个[0 rows × 56 columns]的空DataFrame,代码如下:
import pandas as pd myFile = r"C:\Users\wasp_96b\Desktop\ExcelSheet.xlsx" df1 = pd.read_excel(myFile, sheet_name = 'Sheet1') df2 = (pd.wide_to_long(df1.reset_index(), 'A' ,i='index',j='value').reset_index(drop=True)) df2.ffill(axis = 0) df2.insert(2, 'N1', 'ID-' + str(range(1, 1 + len(df2)))) df2.insert(3, 'N2', len(df2)//5) display(df2)
空DataFrame的原因
pd.wide_to_long使用错误:该函数要求列名有统一前缀(如A_1、A_2),但你的原始数据列名不符合这个格式,导致转换后无匹配数据,返回空表。- 未赋值链式操作:
df2.ffill(axis=0)没有重新赋值给df2,Pandas大部分操作返回新对象,原对象不会被修改。 - 逻辑偏离需求:代码完全没按照你列出的7步转换逻辑编写,既没有处理数据块选取,也没做列筛选等核心步骤,自然得不到预期结果。
正确实现方案
以下是严格按需求步骤编写的代码:
import pandas as pd # 读取Excel文件 myFile = r"C:\Users\wasp_96b\Desktop\ExcelSheet.xlsx" df = pd.read_excel(myFile, sheet_name='Sheet1') # 识别数据块:假设数据块之间以空行分隔 block_starts = df[df['A'].notna()].index.tolist() block_ranges = [] for i in range(len(block_starts)): start = block_starts[i] end = block_starts[i+1] - 1 if i < len(block_starts)-1 else df.index[-1] block_ranges.append((start, end)) # 选取每个数据块的前4行 + 最后2行 selected_rows = [] for start, end in block_ranges: # 前4行 selected_rows.extend(range(start, min(start+4, end+1))) # 最后2行(块行数≥2时生效) if end - start + 1 >= 2: selected_rows.extend(range(end-1, end+1)) # 提取选中行并重置索引 df_selected = df.loc[selected_rows].reset_index(drop=True) # 删除最后3个未命名列 df_selected = df_selected.iloc[:, :-3] # 选择A列和E列(若列名不是A/E,需根据实际列名调整) df_filtered = df_selected[['A', 'E']] # 向下填充A列 df_filtered['A'] = df_filtered['A'].ffill(axis=0) # 创建N1列:生成ID-01至ID-xx的序列 df_filtered['N1'] = [f'ID-{str(i+1).zfill(2)}' for i in range(len(df_filtered))] # 创建N2列:拼接数据块首个值及其编号 block_ids = [] current_block = 0 for idx in df_selected.index: while current_block < len(block_ranges)-1 and idx >= block_ranges[current_block+1][0]: current_block += 1 block_ids.append(current_block+1) block_first_vals = [df.loc[start, 'A'] for start, end in block_ranges] df_filtered['N2'] = [f"{block_first_vals[bid-1]}-{bid}" for bid in block_ids] # 查看结果 display(df_filtered)
代码说明
- 数据块识别:通过非空的A列行定位每个数据块的起止位置,若你的数据块分隔方式不同,可调整这部分逻辑。
- 行选取:严格按每个块取前4行+最后2行的规则提取数据。
- 列处理:按要求删除末尾3列、筛选指定列,再填充A列空值。
- 新列生成:N1生成带两位数字的ID序列;N2根据数据块的首个A值和块编号拼接生成。
内容的提问来源于stack exchange,提问作者Timeless
相关产品推荐
相关产品推荐

