首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用.loc在熊猫细胞中插入一组不一致行为

使用.loc在熊猫细胞中插入一组不一致行为
EN

Stack Overflow用户
提问于 2020-06-11 13:21:14
回答 3查看 1.8K关注 0票数 8

这是一个很简单的例子

代码语言:javascript
运行
复制
import pandas
df = pandas.DataFrame()
value_to_be_set = {'1'}

df.loc[0, 'col1'] = value_to_be_set
df['col2'] = None
df.loc[0, 'col2'] = value_to_be_set

print(df.head())

输出

代码语言:javascript
运行
复制
   col1 col2
0    1  {1}

为什么两列的数据类型不同?

Python 3.7.3

熊猫版本: 0.23.4

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-06-11 13:31:10

在第一次赋值中,您从一个集合创建一个num_column,这与可迭代性不同。您请求一个单个元素,并提供一个大小为一个的可迭代元素,因此可以将集合的内容影响到单个单元格。您可以尝试使用一组2的值,以确保它会引发错误。

在第二个赋值中,您将更新现有列中的单元格。熊猫没有理由在这里打开任何东西,而且它会影响到对细胞的设定。

老实说,这解释了发生了什么,但并不是不同行为背后的理由.

票数 7
EN

Stack Overflow用户

发布于 2020-06-11 13:51:31

当您将value_to_be_set对象展开为大于一个元素时,会发生以下错误:

代码语言:javascript
运行
复制
Traceback (most recent call last):
  File "<pyshell#314>", line 1, in <module>
    df.loc[0, 'col1'] = value_to_be_set
  File "C:\Users\rook\Projects\Sandbox\env\lib\site-packages\pandas\core\indexing.py", line 671, in __setitem__
    self._setitem_with_indexer(indexer, value)
  File "C:\Users\rook\Projects\Sandbox\env\lib\site-packages\pandas\core\indexing.py", line 850, in _setitem_with_indexer
    self._setitem_with_indexer(new_indexer, value)
  File "C:\Users\rook\Projects\Sandbox\env\lib\site-packages\pandas\core\indexing.py", line 1019, in _setitem_with_indexer
    "Must have equal len keys and value "
ValueError: Must have equal len keys and value when setting with an iterable

然而,当您在初始化列之后为'col2'调用它时,就不会发生这种情况。

查看我的__setitem__1.0.3上的env源代码可以发现:

代码语言:javascript
运行
复制
def __setitem__(self, key, value):
    if isinstance(key, tuple):
        key = tuple(com.apply_if_callable(x, self.obj) for x in key)
    else:
        key = com.apply_if_callable(key, self.obj)
    indexer = self._get_setitem_indexer(key)
    self._setitem_with_indexer(indexer, value)

在github上的1.0.4当前分支中,最后一行已更改为下面:

代码语言:javascript
运行
复制
def __setitem__(self, key, value):
    # ... same as above ... #
    self._has_valid_setitem_indexer(key)

    iloc = self if self.name == "iloc" else self.obj.iloc
    iloc._setitem_with_indexer(indexer, value)

然而,_has_valid_setitem_indexer似乎仍在开发中:

代码语言:javascript
运行
复制
def _has_valid_setitem_indexer(self, indexer) -> bool:
    """
    Validate that a positional indexer cannot enlarge its target
    will raise if needed, does not modify the indexer externally.
    Returns
    -------
    bool
    """
    if isinstance(indexer, dict):
        raise IndexError("iloc cannot enlarge its target object")
    else:
        if not isinstance(indexer, tuple):
            indexer = _tuplify(self.ndim, indexer)
        for ax, i in zip(self.obj.axes, indexer):
            if isinstance(i, slice):
                # should check the stop slice?
                pass
            elif is_list_like_indexer(i):
                # should check the elements?
                pass
            elif is_integer(i):
                if i >= len(ax):
                    raise IndexError("iloc cannot enlarge its target object")
            elif isinstance(i, dict):
                raise IndexError("iloc cannot enlarge its target object")

    return True

无论如何,我建议将此作为错误提交,因为它在最新版本的1.0.4中仍然是可复制的。

代码语言:javascript
运行
复制
>>> df.loc[0, 'col1'] = v2
>>> df['col2'] = None
>>> df.loc[0, 'col2'] = v2
>>> df
  col1 col2
0    1  {1}
>>> pd.__version__
'1.0.4'

如果将同一项插入到第二个索引中,则很明显是荒谬的:

代码语言:javascript
运行
复制
>>> df = pd.DataFrame()
>>> df.loc[0, 'col1'] = v
>>> df.loc[1, 'col1'] = v
>>> df
  col1
0    1
1  {1}

我认为使用loc设置新列是错误的,实际上是因为隐含的解包。

票数 3
EN

Stack Overflow用户

发布于 2020-06-11 14:13:51

代码语言:javascript
运行
复制
import pandas
df = pandas.DataFrame()
value_to_be_set = {'1'}

df.loc[0, 'col1'] = value_to_be_set
df['col2'] = None
df.loc[0, 'col2'] = value_to_be_set

print(df.head())

在这里,您可以在col1中直接发送这个值,就像它接受可迭代的set一样,然后遍历它来设置值,然后在那里找到1作为元素,然后设置它。

在第二种情况下,您将col2设置为None,因此在本例中,整个集合被视为一个元素,并将{1}设置为一个值。

代码语言:javascript
运行
复制
import pandas
df = pandas.DataFrame()
value_to_be_set = {'1'}

df.loc[0, 'col1'] = value_to_be_set
#comment down
#df['col2'] = None
df.loc[0, 'col2'] = value_to_be_set

print(df.head())

在注释None之后,col2的值与col1相同。

代码语言:javascript
运行
复制
 col1 col2
0    1    1
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62325417

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档