【问题标题】:Pandas: Appending a row of boolean values to df using `loc` changes to `int`Pandas:使用`loc`将一行布尔值附加到df到`int`
【发布时间】:2021-04-01 20:59:18
【问题描述】:

考虑df

In [2098]: df = pd.DataFrame({'a': [1,2], 'b':[3,4]})

In [2099]: df
Out[2099]: 
   a  b
0  1  3
1  2  4

现在,我尝试将 list 的值附加到 df

In [2102]: df.loc[2] = [3, 4]

In [2103]: df
Out[2103]: 
   a  b
0  1  3
1  2  4
2  3  4

到目前为止一切都很好。

但是现在当我尝试用布尔值列表追加一行时,它会将其转换为int

In [2104]: df.loc[3] = [True, False]

In [2105]: df
Out[2105]: 
   a  b
0  1  3
1  2  4
2  3  4
3  1  0

我知道我可以将df 转换为str,然后可以附加布尔值,例如:

In [2131]: df = df.astype(str)
In [2133]: df.loc[3] = [True, False]

In [2134]: df
Out[2134]: 
      a      b
0     1      3
1     2      4
3  True  False

但是,我想知道这种行为背后的原因。为什么当我将boolean 附加到它时,它不会自动将列的dtypes 更改为object

我的熊猫版本是:

In [2150]: pd.__version__
Out[2150]: '1.1.0'

【问题讨论】:

  • '1.1.0' 是我的熊猫版本。
  • 在我看来,不推荐混合类型,所以它应该可以工作。如果使用df.append(pd.Series([True, False], index=['a','b']), ignore_index=True ),同样的问题
  • @MayankPorwal 因为正如我在 Python 中所说的(不确定 pandas 和 numpy 是否相同),布尔值是整数的子类:docs.python.org/3/reference/datamodel.html#index-10
  • 同意 Dani ,因为 python 布尔值是二进制整数:1+True 返回 2,与添加 TrueFalse 时返回二进制整数的方式相同
  • @jezrael 是的,系列也有同样的问题。

标签: python pandas dataframe boolean


【解决方案1】:

当你执行df.loc[0] 时,它会转换为pd.Series,如下所示:

>>> type(df.loc[0])
<class 'pandas.core.series.Series'>

现在,Series 将只有一个 dtype。所以它将booleans 强制转换为整数。

因此,如果您尝试获取行,则修复方法是使用df.loc[[0]]

>>> type(df.loc[[0]])
<class 'pandas.core.frame.DataFrame'>

但在这种情况下,您需要创建 2 个新的空行,然后使用 df.loc[[...]] 添加值,因为 df.loc[[...]] 仅用于索引,您不能使用它分配新行。

因此,您可以通过df.loc[[...]] 获取行:

>>> df = pd.DataFrame({'a': [1,2], 'b':[3,4]})
>>> df.loc[0]
a    1
b    3
Name: 0, dtype: int64
>>> df.loc[[0]]
   a  b
0  1  3
>>> 

在这里您可以看到不同之处,第一个代码转换为 Series,只有一个 dtype,而第二个代码给出了 DataFrame

但是对于这种情况,您不能使用df.loc[[...]],因为您不能使用它分配东西,所以您只能创建新的空行然后使用df.loc[[...]]

>>> df = pd.DataFrame({'a': [1,2], 'b':[3,4]})
>>> df
   a  b
0  1  3
1  2  4
>>> df.loc[2] = [3, 4]
>>> df
   a  b
0  1  3
1  2  4
2  3  4
>>> df.loc[3] = 0
>>> df
   a  b
0  1  3
1  2  4
2  3  4
3  0  0
>>> df.loc[[3]] = [True, False]
>>> df
      a      b
0     1      3
1     2      4
2     3      4
3  True  False
>>> 

【讨论】:

    【解决方案2】:

    为什么当我将布尔值附加到它时,它不会自动将列的 dtypes 更改为对象?

    因为类型正在向上转换(参见upcasting),来自文档:

    当与其他类型结合时,类型可能会被向上转换, 意味着它们是从当前类型提升的(例如 int 到 float)。

    根据 numpy 规则进行向上转换

    向上转换总是根据 numpy 规则。如果两个不同 dtypes 参与操作,那么更通用的将是 用作运算的结果。

    要了解 numpy 规则 是如何应用的,您可以使用函数find_common_type,如下所示:

    res = np.find_common_type([bool, np.bool], [np.int32, np.int64])
    print(res)
    

    输出

    int64
    

    【讨论】:

    • 非常感谢您的解释。
    猜你喜欢
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 2019-04-17
    • 2015-08-22
    • 2018-12-21
    • 2021-04-03
    相关资源
    最近更新 更多