python - 为什么 Pandas 允许非唯一索引?
问题描述
Pandas 允许唯一和非唯一索引。一些操作只允许唯一索引。在什么情况下使用非唯一索引有意义?我认为强制索引的唯一性可以帮助提前发现数据完整性问题。
解决方案
免责声明:独特RangeIndex
的永远是性能最好的选择。这个问题似乎倾向于使用唯一索引,并且专门寻找需要允许非唯一索引的情况。出于这个原因,从现在开始,将不讨论唯一索引,也不会讨论性能,只讨论非唯一索引的有用好处。
每当我们需要跟踪数据的原始来源时,一般位置非唯一索引是可取的。在很多情况下,在中间阶段,我们需要知道数据在哪一行。这让我们可以计算如果索引是唯一的,这些信息可能会丢失,或者需要添加一个额外的列来跟踪它。下面只是几个例子:
交错多个数据帧:
考虑以下 2 个 DataFrame,假设每个 DataFrame 代表一天的数据。我们想按样本数而不是按天查看此每日数据:
df1 = pd.DataFrame([['10:05', 'Day 1', 'Sample 1'],
['11:14', 'Day 1', 'Sample 2']])
df2 = pd.DataFrame([['10:03', 'Day 2', 'Sample 1'],
['11:12', 'Day 1', 'Sample 2']])
# df1
0 1 2
0 10:05 Day 1 Sample 1
1 11:14 Day 1 Sample 2
#df2
0 1 2
0 10:03 Day 2 Sample 1
1 11:12 Day 1 Sample 2
因为 pandas 允许非唯一索引,所以我们concat
可以sort_index
:
pd.concat([df1, df2]).sort_index()
0 1 2
0 10:05 Day 1 Sample 1
0 10:03 Day 2 Sample 1
1 11:14 Day 1 Sample 2
1 11:12 Day 1 Sample 2
请注意,这是按行索引交错两个 DataFrame 的最快方法。另请注意,按列排序是不可行的1
,2
因为单词Day 1
Sample 1
等将按字典顺序排序,这将遇到诸如 之类的值的问题Day 10
,或者需要大量额外的计算才能正确处理数值。
我们可以添加ignore_index=True
到sort_index
,但这只会隐藏用新的范围索引覆盖,并且仍然依赖于concat
返回具有非唯一索引的 DataFrame 的事实。
pd.concat([df1, df2]).sort_index(ignore_index=True)
0 1 2
0 10:05 Day 1 Sample 1
1 10:03 Day 2 Sample 1
2 11:14 Day 1 Sample 2
3 11:12 Day 1 Sample 2
爆炸和减少
explode
,特别是在 Series 上,是一种常见的操作,并且不丢失索引(允许重复)使得扩展和减少类型操作变得更加容易。
目标是从列中的逗号分隔字符串中删除任何重复值:
df = pd.DataFrame({
'corresponding_id': [10, 20, 30],
'col': ['a,b,c,a', 'b,c,c,b', 'a,a,a,a']
})
df
:
corresponding_id col
0 10 a,b,c,a
1 20 b,c,c,b
2 30 a,a,a,a
一个常见的解决方案可能类似于:
df['col'] = (
df['col'].str.split(',').explode()
.groupby(level=0).apply(lambda s: ','.join(np.unique(s)))
)
df
:
corresponding_id col
0 10 a,b,c
1 20 b,c
2 30 a
爆炸后的结果如下:
df['col'].str.split(',').explode()
0 a
0 b
0 c
0 a
1 b
1 c
1 c
1 b
2 a
2 a
2 a
2 a
Name: col, dtype: object
groupby
因为我们可以相对于(索引)有重复level=0
的索引,所以这只有在索引被保留时才有可能。如果索引不允许重复,我们将拥有:
0 a
1 b
2 c
3 a
4 b
5 c
6 c
7 b
8 a
9 a
10 a
11 a
Name: col, dtype: object
无法轻松确定值来自哪些行,因此更难以将它们放回原处。
扩展 DataFrame
使用重复标签从 DataFrame 中进行选择的能力对于扩展 DataFrame 非常有帮助。
df = pd.DataFrame({
'Count': [2, 4],
'Value': [1, 6]
})
有时我们需要扩展 DataFrame,在这些情况下,我们使用loc
从 DataFrame 中进行选择:
df.loc[[0, 0, 1, 1, 1, 1], :]
注意结果是:
Count Value
0 2 1
0 2 1
1 4 6
1 4 6
1 4 6
1 4 6
我们能够根据重复标签从 DataFrame 中多次选择同一行(并且结果索引是非唯一的)。这很常见,以至于有一种方法Index.repeat
可以根据列动态执行此操作:
df.loc[df.index.repeat(df['Count']), :]
Count Value
0 2 1
0 2 1
1 4 6
1 4 6
1 4 6
1 4 6
推荐阅读
- javascript - 如何在 Kotlin 编译为 JavaScript 中创建“选项对象”(具有许多可选属性的对象)?
- python - await user pins in discord.py?
- php - 警告:advanced_custom_search() 的参数 2 应为参考
- c - 我可以使用 SocketCAN 读取 CRC 和 ACK 位吗?
- php - 标识符“socket”已被声明
- python - 带日期的 SQLAlchemy 文字引发:查询参数的输入无效(预期 str,得到日期)
- c# - RabbitMQ - 发送自定义消息发布/订阅
- vba - VBA 检查安装的软件版本 HKEY_LOCAL_MACHINE
- pytest - 我们可以并行运行多个标记吗?
- email - Postfix Bounce Header 中的自定义 Header 信息