我有一个包含id
,event
和metric
列的数据集:
df = pd.DataFrame([['a','x', 1],
['a','x',2],
['b','x',3],
['b','x',3],
['a','z',4],
['a','z',5],
['b','y',5]], columns = ['id','event','metric'])
id event metric
0 a x 1
1 a x 2
2 b x 3
3 b x 3
4 a z 4
5 a z 5
6 b y 5
我需要在每个event
中找到最后一个id
,并获得带有该event
的行以及上面带有此id
的所有行。结果数据框应为此类切片与以下列的串联:
所需的输出:
index new_id
0 0 ax
1 1 ax
2 2 bx
3 3 bx
4 0 az
5 1 az
6 4 az
7 5 az
8 2 by
9 3 by
10 6 by
我用以下代码产生了所需的输出:
df['id_event'] = df.id + df.event
id_events = df.id_event.unique()
df_all = pd.DataFrame()
for i,id_event in (enumerate(id_events)):
id = id_event[:1]
event = id_event[1:]
last_row_id = df[df.event==event].iloc[-1].name
temp = df.iloc[: last_row_id +1][df.id==id]
temp['new_id'] = id_event
df_all = pd.concat([df_all, temp.reset_index()], axis=0, sort=False)
df_all.reset_index()[['index', 'new_id']]
问题是我大约有2000万行,因此大约需要20个小时才能得到结果。我正在尝试以有效的方式解决此问题,例如没有循环。
答案 0 :(得分:0)
主要的性能问题是您每次迭代都调用pd.concat()
,这很昂贵。试试这个:
results = [] # added
for i,id_event in (enumerate(id_events)):
id = id_event[:1]
event = id_event[1:]
last_row_id = df[df.event==event].iloc[-1].name
temp = df.iloc[: last_row_id +1][df.id==id]
temp['new_id'] = id_event
results.append(temp.reset_index()) # changed
df_all = pd.concat(results, sort=False) # changed
这应该节省很多时间-让我们知道多少。
还要注意,df[df.event==event].iloc[-1].name
可以更简单地写为df[df.event==event].index[-1]
。