以字符串元组为索引的 Pandas DataFrame

Posted

技术标签:

【中文标题】以字符串元组为索引的 Pandas DataFrame【英文标题】:Pandas DataFrame with tuple of strings as index 【发布时间】:2017-03-04 08:07:29 【问题描述】:

我在这里感觉到了一些奇怪的 pandas 行为。我有一个看起来像的数据框

df = pd.DataFrame(columns=['Col 1', 'Col 2', 'Col 3'],
                  index=[('1', 'a'), ('2', 'a'), ('1', 'b'), ('2', 'b')])

In [14]: df
Out[14]:
       Col 1 Col 2 Col 3
(1, a)   NaN   NaN   NaN
(2, a)   NaN   NaN   NaN
(1, b)   NaN   NaN   NaN
(2, b)   NaN   NaN   NaN

我可以设置任意元素的值

In [15]: df['Col 2'].loc[('1', 'b')] = 6

In [16]: df
Out[16]:
       Col 1 Col 2 Col 3
(1, a)   NaN   NaN   NaN
(2, a)   NaN   NaN   NaN
(1, b)   NaN     6   NaN
(2, b)   NaN   NaN   NaN

但是当我去引用我刚刚使用相同语法设置的元素时,我得到了

In [17]: df['Col 2'].loc[('1', 'b')]
KeyError: 'the label [1] is not in the [index]'

谁能告诉我我做错了什么或为什么会发生这种行为?我是否根本不允许将索引设置为多元素元组?

编辑

显然,将元组索引包装在列表中是可行的。

In [38]: df['Col 2'].loc[[('1', 'b')]]
Out[38]:
(1, b)    6
Name: Col 2, dtype: object

虽然在我的实际用例中我仍然会遇到一些奇怪的行为,所以很高兴知道这是否不推荐使用。

【问题讨论】:

this question 中的响应表明不推荐使用,因为元组键和 MultiIndex 选择之间存在歧义。 【参考方案1】:

选择括号中的元组被视为包含您要检索的元素的序列。就像您将 ['1', 'b'] 作为参数传递一样。因此 KeyError 消息:pandas 试图找到密钥 '1',但显然没有找到。

这就是为什么当你添加额外的括号时它会起作用,因为现在参数变成了一个元素的序列 - 你的元组。

您应该避免在选择时处理列表和元组参数的歧义。根据索引是简单索引还是多索引,行为也可能有所不同。

无论如何,如果您在这里询问建议,我看到的是您应该尽量不要构建由元组组成的简单索引:如果您实际构建多索引,pandas 会更好地工作并且使用起来会更强大:

df = pd.DataFrame(columns=['Col 1', 'Col 2', 'Col 3'],
                  index=pd.MultiIndex.from_tuples([('1', 'a'), ('2', 'a'), ('1', 'b'), ('2', 'b')]))

df['Col 2'].loc[('1', 'b')] = 6

df['Col 2'].loc[('1', 'b')]
Out[13]: 6

df
Out[14]: 
    Col 1 Col 2 Col 3
1 a   NaN   NaN   NaN
2 a   NaN   NaN   NaN
1 b   NaN     6   NaN
2 b   NaN   NaN   NaN

【讨论】:

以上是关于以字符串元组为索引的 Pandas DataFrame的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有元组键的 python 字典转换为 pandas 多索引数据框?

JSON序列化以元组为键的字典

Python常见序列详解

如何在 Scala 中以元组为键合并 Maps

pandas使用pd.MultiIndex.from_tuples函数生成多层索引结构(MultiIndex)输入数据为元组列表(列表中包含多个元组)names参数指定多层索引的名称

pandas使用pd.MultiIndex.from_tuples函数生成多层索引结构(MultiIndex)输入数据为元组列表(列表中包含多个元组)names参数指定多层索引的名称