Pandas支持使用唯一和非唯一索引。某些操作只允许使用唯一索引。在什么情况下使用非唯一索引是有意义的呢?我认为强制索引的唯一性可以帮助及早发现数据完整性问题。
RangeIndex
始终是最高效的选项。本问题似乎更喜欢使用唯一索引,并且专门寻找允许非唯一索引的情况。因此,从现在开始,将不讨论唯一索引,也不考虑性能,仅讨论非唯一索引的有用好处。考虑以下两个数据框,假设每个数据框代表一天的数据。我们想按样本编号而不是按天来查看这些每日数据:
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
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
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
level=0
(即索引)进行groupby
,这只有在保留索引的情况下才可能。如果索引不允许重复,我们将会有: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进行扩展。
df = pd.DataFrame({
'Count': [2, 4],
'Value': [1, 6]
})
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
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
在编程中,有不同的操作需要(至少是暂时地)保留非唯一索引值,以便能够理解相应行来自哪里/哪些行归属于一起。这些操作包括:
通常,在某个时间点上重新索引或重置索引可能会更有意义,因为从性能角度来看,非唯一索引可能会产生巨大影响,特别是未排序的情况下。
df.explode
的操作,有必要保留非唯一的索引以指示这些行最初属于同一组。 - Henry Yik