在Pandas中有效地切片和连接数据帧

时间:2019-11-17 02:13:18

标签: python pandas dataframe

我有一个包含ideventmetric列的数据集:

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的所有行。结果数据框应为此类切片与以下列的串联:

  1. 原始df中的索引
  2. 新的ID形成为我们过去获取的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个小时才能得到结果。我正在尝试以有效的方式解决此问题,例如没有循环。

1 个答案:

答案 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]