我有一个有约100万行和约10万个唯一事件的DataFrame。有1列Won
,其中每个事件的每一行都设置为True,事件中的每一行都设置为False。
即
Event ID Runner ID Won
E1 R1 True
E1 R2 False
E1 R3 False
E2 R4 True
E2 R5 False
E2 R6 False
最后我想得到一个平衡的DataFrame,每个组只有1个获胜者,只有1个非获胜者。
即
Event ID Runner ID Won
E1 R1 True
E1 R3 False
E2 R4 True
E2 R5 False
我不在乎每个事件选择哪个非赢家,只要有1个赢家,一个非赢家即可。
对于大熊猫,我已经尝试了一些方法,选择了获胜者和未获胜者,
_won = df.Won
winners = df[_won]
non_winners = df[~_won]
但是我所见过的每个种族试图选择1个非获胜者的每个过程都非常缓慢-每个事件只需几秒钟(如果您有10万个事件,这是IMO的不合理)。
与group
和apply
一起拍摄,
new_df = winners.append(
non_winners
.groupby('Event ID')
.apply(lambda grp: grp.sample(1))
遍历groupby,
for event_id, grp in non_winners.groupby('Event ID'):
winners.append(grp.sample(1))
遍历获胜者的活动ID,
event_ids = set(winners['Event ID'].drop_duplicates())
for event_id in event_ids:
winners.append(
non_winners[non_winners['Event ID'] == event_id].sample(1))
但是在处理约100万个事件和约10万个事件时,每个选项似乎都非常慢。
答案 0 :(得分:5)
使用groupby
和head
。
df.groupby(['Event ID', 'Won']).head(1)
Event ID Runner ID Won
0 E1 R1 True
1 E1 R2 False
3 E2 R4 True
4 E2 R5 False
只要您对输出保持平衡,就不会对输出中保留的内容保持谨慎。
还有drop_duplicates
。
df.drop_duplicates(subset=['Event ID', 'Won'], keep='last')
# or keep='first', it doesn't matter
Event ID Runner ID Won
0 E1 R1 True
2 E1 R3 False
3 E2 R4 True
5 E2 R6 False
最后,如果您想实施改组,请事先致电sample
:
(df.sample(frac=1)
.sort_values(by=['Event ID'])
.drop_duplicates(['Event ID', 'Won'])
)
Event ID Runner ID Won
2 E1 R3 False
0 E1 R1 True
4 E2 R5 False
3 E2 R4 True
答案 1 :(得分:0)
我想出了一个让我对速度足够满意的选择,就是将混洗和重复复制到非赢家的行上,
_won = df.Won
winners = df[_won]
_non_winners = shuffle(df[~_won])
non_winners = _non_winners[~_non_winners.duplicated('Event ID')]
new_df = winners.append(non_winners)
在其他选项中,每个组花费大约一秒钟的时间,这对于它在整个数量的组中运行是不可持续的,而据我所知,此解决方案给出的结果完全相同,但是大约10秒,相比之下我不知道要多久。
如果您希望每个分组多于1个,这很奇怪,但可能的话,您只需再次进行基本相同的操作即可,
...
_non_winners = shuffle(df[~_won])
dupeys = _non_winners.duplicated('Event ID')
new_df = pandas.concat([
winners,
_non_winners[~dupeys]])
_non_winners = _non_winners[dupeys]
new_df = pandas.concat([
new_df,
_non_winners[~_non_winners.duplicated('race_event_id')]])