将列表插入单元格 - 为啥 loc 实际上在这里工作?

Posted

技术标签:

【中文标题】将列表插入单元格 - 为啥 loc 实际上在这里工作?【英文标题】:Inserting list into a cell - why does loc ACTUALLY work here?将列表插入单元格 - 为什么 loc 实际上在这里工作? 【发布时间】:2019-06-21 08:18:27 【问题描述】:

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

在解决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'),使用 at 就足够了,例如 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 为什么要这样做?这是记录在案的行为,还是错误?

【问题讨论】:

这在我看来像是一个不受支持的功能,你可以称之为错误或不一致,当然存储非标量类型是不明智的。有趣的是,.at 的使用限制较少 【参考方案1】:

这是因为loc 执行bunch 检查它支持的所有许多用例。 (注意:历史是 lociloc 是为了消除 ix 的歧义而创建的,早在 2013 年 v0.11 中,但即使在今天,loc 仍然存在很多歧义。)

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

单个元素(在本例中,当 1/'B' 存在唯一索引/列时)。 一个系列(如果 1/'B' 之一多次出现在索引/列中)。 一个 DataFrame(如果 BOTH 1/'B' 出现在索引/列中多次)。

除此之外:iloc 在这种情况下会遇到同样的问题,尽管它总是第一种情况,但这可能是因为 loc 和 iloc 共享此分配代码。

因此,pandas 需要支持所有这些情况进行分配!

分配逻辑的早期部分将列表(列表)转换为 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]

这仍然不理想,但重申lociloc 中有太多边缘情况,解决方案应尽可能明确以避免它们(在此处使用at)。如您所知,更一般地,避免在 DataFrame 中使用列表!

【讨论】:

哦,我想我还没回答第二部分。 答案是“它偷偷溜走”(我链接到的一堆支票)。稍后我会尝试用更具体的内容对其进行修改。 所以“状态设计”? :D @coldspeed status-by-duct-taped-together-working-well-enough :)

以上是关于将列表插入单元格 - 为啥 loc 实际上在这里工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 df.loc 从数据帧的特定单元格返回值(数字)?

将列表插入满足列条件的单元格中

在熊猫数据框单元格中插入列表

在Excel里,日期为啥变成了数字

UICollectionView 插入动画单元格立即出现,后面跟着实际的动画单元格

为啥我的 iPhone UITableView 原型单元格图像水平移动?