Pandas ищет значения в одном столбце на основе списка значений другого столбца

#python #pandas

#python #pandas

Вопрос:

У меня есть фрейм данных со столбцами и идентификаторами и значениями.

 df=
id    val
'a'    1
'b'    3
'c'    9 
  

….

У меня есть список (повторяющихся) значений идентификаторов.

 i_list=['a','a','a','b']
  

Мне нужно сопоставить этот список (повторяющихся) значений идентификаторов в соответствующие (повторяющиеся) столбцы значений, используя пары фреймов данных (id, val)

 out_desired=[1,1,1,3]
  

Прямо сейчас я делаю:

 out_desired=[df[df.id==curr_id].val.values for curr_id in i_list ]
  

Как сделать это более эффективным, но в то же время кратким способом?

Ответ №1:

Вы можете попробовать использовать pandas.merge , поскольку мне кажется, что это быстрее.

 df = {'id': ['a', 'b', 'c'], 'value': [1,3,9]}
df = pd.DataFrame(df).set_index('id')
test = ['a', 'b', 'c']*8
  
 %timeit df.merge(pd.DataFrame({'id':test}), left_index=True, right_on='id', how='right')['value'].values
1.32 ms ± 33.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  
 %timeit [df[df.index==curr_id].values for curr_id in test ]
5.81 ms ± 123 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
  

Я считаю, что это дает правильный ответ

Ответ №2:

Если id s отсортированы по лексике, вы можете использовать Series.searchsorted :

 df.loc[df['id'].searchsorted(i_list), 'val'].to_numpy().tolist()
[1, 1, 1, 3]
  

Или вы можете установить id как индекс (работает и для не отсортированных id ):

 df.set_index('id').loc[i_list, 'val'].to_numpy().tolist()
# [1, 1, 1, 3]
  

Если id столбец не отсортирован, выполните сортировку, а затем выполните описанные выше действия для первого подхода к работе:

 print(df)
  id  val
0  c    1
1  b    3
2  a    9

df_ = df.sort_values(['id'])
df_.loc[df_['id'].searchsorted(i_list), 'val'].to_numpy().tolist()
[1, 1, 1, 3]
  

Комментарии:

1. Второй подход может быть быстрее @ 00__00__00 установка в качестве индекса

2. Я оставлю вопрос открытым на пару дней, поскольку другие ответы также могут быть полезны

3. Вы проверили, работает ли второй подход быстрее? Я думаю, что это проще и должно быть быстрее @ 00__00__00