python-将列表插入到单元格中-为什么loc在这里实际起作用?

我们知道设置单个单元格的标准方法是使用at或iat.但是,我注意到一些有趣的行为,我想知道是否有人可以合理化.

在求解this question时,我遇到了loc的一些奇怪行为.

# Setup.

pd.__version__
# '0.24.0rc1'

df = pd.DataFrame({'A': [12, 23], 'B': [['a', 'b'], ['c', 'd']]})
df
    A       B
0  12  [a, b]
1  23  [c, d]

要设置单元格(1,’B’),只需使用df.at [1,’B’] = …即可.但是使用loc时,我最初尝试了此方法,但该方法无效:

df.loc[1, 'B'] = ['m', 'n', 'o', 'p'] 
# ValueError: Must have equal len keys and value when setting with an iterable

所以,我尝试了(也失败了)

df.loc[1, 'B'] = [['m', 'n', 'o', 'p']]
# ValueError: Must have equal len keys and value when setting with an ndarray

我以为loc也可以在这里获取嵌套列表.在一件怪异的事件中,这段代码起作用了:

df.loc[1, 'B'] = [['m'], ['n'], ['o'], ['p']]
df

    A             B
0  12        [a, b]
1  23  [m, n, o, p]

为什么loc这样工作?此外,如果将任何其他元素添加到任何列表中,则会失败:

df.loc[1, 'B'] = [['m'], ['n'], ['o'], ['p', 'q']]
# ValueError: Must have equal len keys and value when setting with an iterable

空列表也不起作用.将每个元素嵌套在自己的列表中似乎没有意义.

loc为什么这样做?是记录的行为还是错误?

解决方法:

发生这种情况是因为loc执行bunch检查所支持的所有用例. (注意:历史是loc和iloc的创建是为了消除ix的歧义,可追溯到2013 v0.11,但即使在今天,loc仍然有很多歧义.)

在这种情况下,df.loc [1,’B’]可以返回:

>单个元素(在这种情况下,当1 /’B’具有唯一的索引/列时).
>系列(如果1 /’B’之一在索引/列中多次出现).
>一个数据框(如果同时在索引/列中同时出现“ 1 / B”).

另外:即使总是第一种情况,iloc在这种情况下也会遇到相同的问题,但这可能是因为loc和iloc共享此分配代码.

因此,大熊猫需要支持所有这些案例才能完成任务!

分配逻辑的早期部分将列表的列表转换为numpy数组:

In [11]: np.array(['m', 'n', 'o', 'p']).shape
Out[11]: (4,)

In [12]: np.array([['m', 'n', 'o', 'p']]).shape
Out[12]: (1, 4)

因此,您不能只传递列表列表并期望获得正确的数组.相反,您可以显式设置为对象数组:

In [13]: a = np.empty(1, dtype=object)

In [14]: a[0] = ['m', 'n', 'o', 'p']

In [15]: a
Out[15]: array([list(['m', 'n', 'o', 'p'])], dtype=object)

现在您可以在作业中使用它:

In [16]: df.loc[0, 'B'] = a

In [17]: df
Out[17]:
    A             B
0  12  [m, n, o, p]
1  23        [c, d]

它仍然不是理想的,但是要重申的是,loc和iloc中有很多边缘情况,解决方案是尽可能明确地避免它们(在此处使用).如您所知,更普遍地,避免在DataFrame中使用列表!

上一篇:python-熊猫:选择两个日期之间的DataFrame行(日期时间索引)


下一篇:MySQL索引的大小限制是什么意思?