Python Pandas 不再像以前那样使用名称字段

Python Pandas not using names field as it once did

我有一个简短的脚本,它是我使用 "pandas>=0.25.3" 编写的应用程序的缩减版,它已升级到我们代码的 "pandas==1.1.5" 最新版本。在此版本的 Pandas 中,默认引擎不解析 xlsx,因此我们添加了 engine="openpyxl"。但是,有一个新问题。 read_excel 似乎不再尊重 names 论点并且有奇怪的行为。

import pandas

filename = "... .xlsx"

names = ["foo", "bar", "baz"]

data_frame = pandas.read_excel(
    filename,
    header=None,
    names=names,
    engine="openpyxl",
    skiprows=3,
    sheet_name=0,
)
print(data_frame.iloc[3])

运行 带有新 Pandas 的脚本我得到这个输出:

foo   NaN
bar   NaN
baz   NaN
Name: (FxK2,SMin, 2066.125), dtype: float64

但之前在 pandas-0.25.3 中默认使用 xlrd 引擎进行解析,我得到了我预期的结果:

foo   FxK2
bar   SMin
baz   2066.125

names 字段为列命名,然后我可以引用 data_frame.iloc[0].baz 并获得 2066.125。现在出于某种原因,整个事情最终都出现在数据框的可选名称字段中。

我怎样才能得到我习惯的行为,这可能是一个错误还是我不习惯的新界面? pandas-1.1.5 似乎确实以我习惯使用它的方式引用了 names 参数。

已更新(评论线程后):

我在使用 engine='openpyxl' 时遇到了第二个 excel 文件的相同问题。但是,当使用 engine='xlrd' 阅读时,我没有遇到问题。但这可能是 xlrd 的版本相关问题,因为我使用的是旧版本“1.2.0”(目前是 2.0.1),并且 xlrd docummentation 中有一个很大的警告说它不不再阅读 .xls 文件以外的任何内容。

因此,正如我们在评论中讨论的那样,使用 engine='openpyxl' 的一种可能的解决方法是使用 usecols=range(3) 指定列,尽管它需要事先了解文件中的列.问题可能隐藏在那些“空”单元格中 formatting/styling/etc。

例如,在同一个有问题的文件中,如果我 select 并将具有值的单元格复制到同一文件中的另一个 Sheet (Sheet1),然后读取它与:

pd.read_excel('redux2.xlsx', sheet_name='Sheet1', header=None, names=['foo','bar','baz'], engine='openpyxl', skiprows=1)

然后它按预期工作。


原答案:

它对我来说按预期工作。可能与您的数据有关。试试下面的代码。如果它有效,那么您就知道它与您的数据有关,而不是 pandas.

示例数据

import string

df = pd.DataFrame({
    'col1': list(string.ascii_letters[:10]),
    'col2': list(string.ascii_letters[10:20]),
    'col3': range(1,11)
})

df.to_excel('file.xlsx', index=False)
print(df)
  col1 col2  col3
0    a    k     1
1    b    l     2
2    c    m     3
3    d    n     4
4    e    o     5
5    f    p     6
6    g    q     7
7    h    r     8
8    i    s     9
9    j    t    10

测试

filename = 'file.xlsx'
names = ["foo", "bar", "baz"]

data_frame = pd.read_excel(
    filename,
    header=None,
    names=names,
    engine="openpyxl",
    skiprows=3,
    sheet_name=0,
)

print(data_frame.iloc[3])
foo    f
bar    p
baz    6
Name: 3, dtype: object

注意:我的 pandas 版本也是“1.1.5”。