gpt4 book ai didi

python - 将 rank 2 numpy 数组分配给 pandas DataFrame 列的行为不一致

转载 作者:太空狗 更新时间:2023-10-29 17:30:36 25 4
gpt4 key购买 nike

我注意到分配给 pandas DataFrame 列(使用 .loc 索引器)的行为因其他列的不同而不同出现在 DataFrame 中并以赋值的确切形式出现。使用三个示例 DataFrame:

df1 = pandas.DataFrame({
'col1': [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
})
# col1
# 0 [1, 2, 3]
# 1 [4, 5, 6]
# 2 [7, 8, 9]
df2 = pandas.DataFrame({
'col1': [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
'col2': [[10, 20, 30], [40, 50, 60], [70, 80, 90]]
})
# col1 col2
# 0 [1, 2, 3] [10, 20, 30]
# 1 [4, 5, 6] [40, 50, 60]
# 2 [7, 8, 9] [70, 80, 90]
df3 = pandas.DataFrame({
'col1': [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
'col2': [1, 2, 3]
})
# col1 col2
# 0 [1, 2, 3] 1
# 1 [4, 5, 6] 2
# 2 [7, 8, 9] 3
x = numpy.array([[111, 222, 333],
[444, 555, 666],
[777, 888, 999]])

我发现了以下内容:

  1. df1:

    1. df1.col1 = x

      结果:

      df1
      # col1
      # 0 111
      # 1 444
      # 2 777
    2. df1.loc[:, 'col1'] = x

      结果:

      df1
      # col1
      # 0 111
      # 1 444
      # 2 777
    3. df1.loc[0:2, 'col1'] = x

      结果:

      # […]
      # ValueError: could not broadcast input array from shape (3,3) into shape (3)
  2. df2:

    1. df2.col1 = x

      结果:

      df2
      # col1 col2
      # 0 111 [10, 20, 30]
      # 1 444 [40, 50, 60]
      # 2 777 [70, 80, 90]
    2. df2.loc[:, 'col1'] = x

      结果:

      df2
      # col1 col2
      # 0 111 [10, 20, 30]
      # 1 444 [40, 50, 60]
      # 2 777 [70, 80, 90]
    3. df2.loc[0:2, 'col1'] = x

      结果:

      # […]
      # ValueError: could not broadcast input array from shape (3,3) into shape (3)
  3. df3:

    1. df3.col1 = x

      结果:

      df3
      # col1 col2
      # 0 111 1
      # 1 444 2
      # 2 777 3
    2. df3.loc[:, 'col1'] = x

      结果:

      # ValueError: Must have equal len keys and value when setting with an ndarray
    3. df3.loc[0:2, 'col1'] = x

      结果:

      # ValueError: Must have equal len keys and value when setting with an ndarray

因此,如果 DataFrame 中的其他列之一没有 dtype object,那么 df.loc 似乎表现不同。

我的问题是:

  • 为什么其他列的存在会影响这种分配?
  • 为什么不同版本的作业不等同?特别是,为什么在不会导致 ValueError 的情况下,DataFrame 列中填充了第一列 numpy 数组?

注意:我不想讨论以这种方式将列分配给 numpy 数组是否有意义。我只想知道行为上的差异,以及这是否算作错误。

最佳答案

Why would the presence of other columns make a difference in this kind of assignment?

答案很简单,因为 Pandas 检查数据框中的混合类型。您可以使用源代码中使用的相同方法自行检查:

print(df1._is_mixed_type)  # False
print(df2._is_mixed_type) # False
print(df3._is_mixed_type) # True

使用的逻辑因 _is_mixed_type 的值而异。具体来说,当您提供的输入的 _is_mixed_typeTrue 时,_setitem_with_indexer 中的以下测试失败:

if len(labels) != value.shape[1]:
raise ValueError('Must have equal len keys and value '
'when setting with an ndarray')

换句话说,数组中的列数多于数据框中要分配给的列数。

这是一个错误吗?在我看来,在 Pandas 数据框中使用任何列表或数组都充满了危险。1 添加了 ValueError 检查以解决一个更重要的问题 ( GH 7551 ) .


Why are the different versions of the assignment not equivalent?

通过 df3['col1'] = x 进行赋值的原因是因为 col1 是一个现有系列。尝试 df3['col3'] = x,您的代码将因 ValueError 而失败。

深入挖掘,datframe 的 __setitem__ 方法(df[] 是语法糖)将 'col1' 标签转换为通过 key = com._apply_if_callable(key, self) 的系列(如果存在):

def _apply_if_callable(maybe_callable, obj, **kwargs):
"""
Evaluate possibly callable input using obj and kwargs if it is callable,
otherwise return as it is
"""
if callable(maybe_callable):
return maybe_callable(obj, **kwargs)
return maybe_callable

然后逻辑可以回避 _setitem_with_indexer 中的检查逻辑。您可以推断出这一点,因为当我们为现有系列提供标签时,我们会跳转到 _setitem_array 而不是 _set_item:

def __setitem__(self, key, value):

key = com._apply_if_callable(key, self)

if isinstance(key, (Series, np.ndarray, list, Index)):
self._setitem_array(key, value)
elif isinstance(key, DataFrame):
self._setitem_frame(key, value)
else:
self._set_item(key, value)

以上均为实现细节;你不应该基于这些底层方法来构建你的 Pandas 语法,因为它们可能会在未来发生变化。


1 我什至会说它应该被禁用 默认 并且只能通过设置启用。这是一种非常低效的存储和操作数据的方式。有时它提供了短期的便利,但以混淆代码为代价。

关于python - 将 rank 2 numpy 数组分配给 pandas DataFrame 列的行为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52080334/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com