这是一个很简单的例子
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 col2
0 1 {1}
为什么两列的数据类型不同?
Python 3.7.3
熊猫版本: 0.23.4
发布于 2020-06-11 13:31:10
在第一次赋值中,您从一个集合创建一个num_column,这与可迭代性不同。您请求一个单个元素,并提供一个大小为一个的可迭代元素,因此可以将集合的内容影响到单个单元格。您可以尝试使用一组2的值,以确保它会引发错误。
在第二个赋值中,您将更新现有列中的单元格。熊猫没有理由在这里打开任何东西,而且它会影响到对细胞的设定。
老实说,这解释了发生了什么,但并不是不同行为背后的理由.
发布于 2020-06-11 13:51:31
当您将value_to_be_set
对象展开为大于一个元素时,会发生以下错误:
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源代码可以发现:
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
当前分支中,最后一行已更改为下面:
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
似乎仍在开发中:
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
中仍然是可复制的。
>>> df.loc[0, 'col1'] = v2
>>> df['col2'] = None
>>> df.loc[0, 'col2'] = v2
>>> df
col1 col2
0 1 {1}
>>> pd.__version__
'1.0.4'
如果将同一项插入到第二个索引中,则很明显是荒谬的:
>>> df = pd.DataFrame()
>>> df.loc[0, 'col1'] = v
>>> df.loc[1, 'col1'] = v
>>> df
col1
0 1
1 {1}
我认为使用loc
设置新列是错误的,实际上是因为隐含的解包。
发布于 2020-06-11 14:13:51
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}设置为一个值。
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相同。
col1 col2
0 1 1
https://stackoverflow.com/questions/62325417
复制相似问题