【问题标题】:Pandas.read_excel sometimes incorrectly reads Boolean values as 1's/0'sPandas.read_excel 有时会错误地将布尔值读取为 1/0
【发布时间】:2019-01-10 17:15:06
【问题描述】:

我需要将一个非常大的 Excel 文件读入 DataFrame。该文件包含字符串、整数、浮点数和布尔数据,以及缺失数据和完全空的行。还可能值得注意的是,某些单元格值是从单元格公式和/或 VBA 派生的 - 尽管理论上这不会影响任何事情。

正如标题所说,pandas 有时会将布尔值读取为 float 或 int 1 和 0,而不是 True 和 False。它似乎与空行的数量和其他数据的类型有关。为简单起见,我只是链接了一个复制问题的 2 页 Excel 文件。 Boolean_1.xlsx

代码如下:

import pandas as pd
df1 = pd.read_excel('Boolean_1.xlsx','Sheet1')
df2 = pd.read_excel('Boolean_1.xlsx','Sheet2')
print(df1, '\n' *2, df2)

这是印刷品。主要注意ZBA行,两张表中的值相同,但DataFrames中的值不同:

  Name stuff  Unnamed: 1 Unnamed: 2 Unnamed: 3
0         AFD          a        dsf        ads
1         DFA          1          2          3
2         DFD      123.3       41.1       13.7
3        IIOP        why        why        why
4         NaN        NaN        NaN        NaN
5         ZBA      False      False       True 

   Name adslfa  Unnamed: 1  Unnamed: 2  Unnamed: 3
0        asdf         6.0         3.0         6.0
1         NaN         NaN         NaN         NaN
2         NaN         NaN         NaN         NaN
3         NaN         NaN         NaN         NaN
4         NaN         NaN         NaN         NaN
5         ZBA         0.0         0.0         1.0

我还能够在我实际处理的大文件中获得整数 1 和 0 的输出(耶),但无法轻松复制它。

什么可能导致这种不一致,有没有办法强制熊猫读取布尔值,因为它们应该被读取?

【问题讨论】:

  • 你知道哪些列应该是布尔值吗?您可以使用 dtype 关键字指定加载列的数据类型
  • 布尔列是否包含缺失或空白单元格?
  • 我知道哪些行是布尔值。从理论上讲,我可以反转行和列,但在加载 DataFrame 之前我不知道该怎么做(此时数据是错误的)。不幸的是,由于我正在做的项目的性质,它需要能够处理空单元格、行和列(尽管我不明白为什么这会影响任何事情)
  • 你也许可以通过transposing the data来躲避这个问题

标签: python excel pandas


【解决方案1】:

Pandas 类型转换按列/系列应用。一般来说,Pandas 不适用于混合类型或object dtype。您应该期望内部化逻辑来确定系列的最有效 dtype。在这种情况下,Pandas 选择了 float dtype 以适用于包含 floatbool 值的系列。在我看来,这既高效又整洁。

但是,正如您所指出的,当您有转置的输入数据集时,这将不起作用。让我们从头开始设置一个示例:

import pandas as pd, numpy as np

df = pd.DataFrame({'A': [True, False, True, True],
                   'B': [np.nan, np.nan, np.nan, False],
                   'C': [True, 'hello', np.nan, True]})

df = df.astype({'A': bool, 'B': float, 'C': object})

print(df)

       A    B      C
0   True  NaN   True
1  False  NaN  hello
2   True  NaN    NaN
3   True  0.0   True

选项 1:更改“行 dtype”

您可以在不转置数据的情况下连续更改对象的 dtype。这将强制系列 B 具有 object dtype,即存储指向任意类型的指针的系列:

df.iloc[3] = df.iloc[3].astype(bool)

print(df)

       A      B      C
0   True    NaN   True
1  False    NaN  hello
2   True    NaN    NaN
3   True  False   True

print(df.dtypes)

A      bool
B    object
C    object
dtype: object

选项 2:转置并转换为布尔值

在我看来,这是更好的选择,因为数据类型被附加到特定类别/输入数据系列。

df = df.T                   # transpose dataframe
df[3] = df[3].astype(bool)  # convert series to Boolean

print(df)

      0      1     2      3
A  True  False  True   True
B   NaN    NaN   NaN  False
C  True  hello   NaN   True

print(df.dtypes)

0    object
1    object
2    object
3      bool
dtype: object

【讨论】:

    【解决方案2】:

    Read_excel 将根据列中具有值的第一行确定每列的 dtype。如果该列的第一行为空,Read_excel 将继续到下一行,直到找到一个值。

    在 Sheet1 中,B、C 和 D 列中具有值的第一行包含字符串。因此,所有后续行都将被视为这些列的字符串。在这种情况下,FALSE = False

    在 Sheet2 中,B、C 和 D 列中值的第一行包含整数。因此,所有后续行都将被视为这些列的整数。在这种情况下,FALSE = 0。

    【讨论】:

    • determine the dtype for each column based on the first row in the column。一般来说,这是不正确的。假设在 A 列中,第一行的编号为 1,第二行的编号为 1.5。然后 A 列将被读入为 float 而不是 int。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 2021-09-20
    相关资源
    最近更新 更多