在DataFrame中按组打乱行,保持组的相对顺序不变
给定以下的数据框(df):
data = {'Org': ['Tom', 'Kelly', 'Rick', 'Dave','Sara','Liz'],
'sum': [3, 4, 4, 4, 5, 5]}
df = pd.DataFrame(data)
# Org sum
# 0 Tom 3
# 1 Kelly 4
# 2 Rick 4
# 3 Dave 4
# 4 Sara 5
# 5 Liz 5
我想要只打乱那一列中的重复值,同时保持其他值的顺序不变。
输出结果应该像这样:
data = {'Org': ['Tom', 'Rick', 'Dave', 'Kelly','Liz','Sara'],
'sum': [3, 4, 4, 4, 5, 5]}
df = pd.DataFrame(data)
# Org sum
# 0 Tom 3
# 1 Rick 4
# 2 Dave 4
# 3 Kelly 4
# 4 Liz 5
# 5 Sara 5
使用 df.sample(frac=1)
会把所有的行都打乱,但这不是我想要的效果。
1 个回答
1
排序的分组
如果你的分组是连续的,并且你想保持它们的相对顺序,可以使用 groupby.sample
:
out = df.groupby('sum', sort=False).sample(frac=1)
示例输出:
Org sum
0 Tom 3
3 Dave 4
1 Kelly 4
2 Rick 4
5 Liz 5
4 Sara 5
如果你想按照总和来排序输出,可以这样做:
out = df.groupby('sum', sort=False).sample(frac=1)
# or
out = df.sample(frac=1).sort_values(by='sum', kind='stable')
这样可以确保分组是排序的,即使输入时它们并不是排序的。
保持原样的分组
相反,如果你想完全保持分组的原始顺序,但仍然想在组内打乱顺序,比如这个例子:
Org sum
0 Tom 3
1 Kelly 4
2 Rick 4
3 Sara 5
4 Liz 5
5 Dave 4 # this is part of group "4" but we want the row to stay there
那么可以使用 groupby.transform
来在原地打乱索引,然后重新索引:
out = df.loc[df.groupby('sum', sort=False)['sum']
.transform(lambda g: g.sample(frac=1).index)]
示例输出:
Org sum
0 Tom 3
2 Rick 4
5 Dave 4
4 Liz 5
3 Sara 5
1 Kelly 4 # the group was shuffled, not the absolute position