Pandas:使用 `loc` 将一行布尔值附加到 df 更改为 `int`

Pandas: Appending a row of boolean values to df using `loc` changes to `int`

考虑 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

我的 Pandas 版本是:

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

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

>>> type(df.loc[0])
<class 'pandas.core.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
>>> 

当我向其附加布尔值时,为什么它没有自动将列的数据类型更改为对象?

因为类型正在 upcasted(参见 upcasting),来自文档:

Types can potentially be upcasted when combined with other types, meaning they are promoted from the current type (e.g. int to float).

向上转换根据 numpy 规则:

Upcasting is always according to the numpy rules. If two different dtypes are involved in an operation, then the more general one will be used as the result of the operation.

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

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

输出

int64