我有以下带有两行标题的电子表格作为工作簿的一部分。
Name Age Genre Monthly Annually Department Region
P1 28 Female 1000 12000 I.T. North
P2 25 Male 1100 13200 I.T. South
P3 29 Female 1500 18000 Human Ressources North
目标是获得一个包含所有数据和一级列的数据框,其中我们得到“./Genre”、“Salary/Monthly”、“Salary/Anually”、“./Department”等。即使单元格 D1 和 E1 被合并,Pandas 也会查看 E1,例如 C1 或 F1(空内容)。
基于这篇文章,我采用以下代码解决了部分问题:
import pandas as pd
minimal_df = test_df = pd.read_excel(io="multiIndex_columns.xlsx", sheet_name="sample", header=None, skiprows=2, nrows=3)
minimal_index = pd.read_excel(io="multiIndex_columns.xlsx", sheet_name="sample", header=None, nrows=2)
如果我们查看
minimal_index
的呈现方式,我们会在第 3 列找到“薪水”,但在第 4 列却找不到。
0 1 2 3 4 5 6
0 NaN NaN NaN Salary NaN NaN NaN
1 Name Age Genre Monthly Anually Department Region
无论如何,在填充辅助数据框中的 NA 值后,就完成了将列名称分配给数据框的操作。
minimal_index.fillna(method='ffill', axis=1, inplace=True)
minimal_df.columns = pd.MultiIndex.from_arrays(minimal_index.values)
nan/Name nan/Age nan/Genre Salary/Monthly Salary/Annually Salary/Department Salary/Region
P1 28 Female 1000 12000 I.T. North
P2 25 Male 1100 13200 I.T. South
P3 29 Female 1500 18000 Human Ressources North
上图,我们通过PyCharm Community Edition 2023.1.4查看最终结果。然而,由于
fillna()
使用的“填充”方法,部门和地区列也与薪资相关。另一方面,除了在前三列上保留 NaN 值之外,我什么也不能分配,因为 fillna()
不能同时允许“值”和“方法”参数。
有没有办法同时解决这两部分,避免 Excel 修改文件?基于 Pandas 或其他库的什么解决方案可以识别输入单元格的合并?
我认为这对熊猫来说是不可能的。我会使用 openpyxl 来处理 merged 单元格:
import openpyxl
ws = openpyxl.load_workbook("file.xlsx")["sample"]
TR, BR = 1, 2 # <-- top and bottom rows holding the header
SR = 3 # <-- the row indice where the table starts (excluding the header)
def get_val(x, sheet=ws):
if isinstance(x, openpyxl.cell.cell.MergedCell):
for r in sheet.merged_cells.ranges:
if r.__contains__(x.coordinate):
return r.start_cell.value
else:
return x.value if x.value else ""
header = [
f"{get_val(c1)}/{get_val(c2)}" if get_val(c1) else f"./{c2.value}"
for (c1,c2) in zip(ws[TR], ws[BR])
]
data = [row for row in ws.iter_rows(min_row=SR, values_only=True)]
df = pd.DataFrame(data, columns=header)
输出(df):
信息/姓名 | 信息/年龄 | 信息/类型 | ./Id | 工资/月薪 | 薪资/年薪 | ./部门 | ./地区 |
---|---|---|---|---|---|---|---|
P1 | 28 | 女 | id001 | 1000 | 12000 | I.T. | 北 |
P2 | 25 | 男 | id002 | 1100 | 13200 | I.T. | 南 |
P3 | 29 | 女 | id003 | 1500 | 18000 | 人力资源 | 北 |
使用的输入(file.xlsx):
看起来“薪水”最初是跨 2 个合并的 EXCEL 单元格(D1、E1)。
取消合并这些,然后将 D1 复制到 E1,应该会产生如您所期望的
minimal_index
。