2015-06-03 4 views
2

У меня есть столбец в моем кадре данных со строковыми данными. Мне нужно создать новый столбец целых чисел, по одному для каждой уникальной строки. Я буду использовать этот столбец как второй уровень мультииндекса. Код ниже делает трюк, но мне было интересно, может ли быть более эффективное решение для Pandas?Новый столбец для данных pandas dataframe в соответствии со значениями из другого столбца

import pandas as pd 
df = pd.DataFrame({'c1':[1,2,3,4], 
        'c2':['a','a','b','b']}) 

for i,e in enumerate(df.c2.unique()): 
    df.loc[df.c2 == e,'c3'] = i 

ответ

4
for i,e in enumerate(df.c2.unique()): 
    df.loc[df.c2 == e,'c3'] = i 

можно заменить

df['c3'] = pd.Categorical(df['c2']).codes 

Даже для этого небольшого DataFrame, используя Категорический является (около 4х) быстрее:

In [33]: %%timeit 
...:  for i,e in enumerate(df.c2.unique()): 
      df.loc[df.c2 == e,'c3'] = i 
1000 loops, best of 3: 1.07 ms per loop 

In [35]: %timeit pd.Categorical(df['c2']).codes 
1000 loops, best of 3: 264 µs per loop 

Улучшение скорости будет увеличиваться с количеством уникальных элементов в df['c2'], поскольку относительная неэффективность Python for-loop станет более очевидной при увеличении количества итераций.

Например, если

import string 
import numpy as np 
import pandas as pd 

N = 10000 
df = pd.DataFrame({'c1':np.arange(N), 
        'c2':np.random.choice(list(string.letters), size=N)}) 

затем с помощью Категориальные является (около 56x) быстрее:

In [53]: %%timeit 
....:  for i,e in enumerate(df.c2.unique()): 
       df.loc[df.c2 == e,'c3'] = i 
10 loops, best of 3: 58.2 ms per loop 

In [54]: %timeit df['c3'] = pd.Categorical(df['c2']).codes 
1000 loops, best of 3: 1.04 ms per loop 

Тесты выше, были сделаны с IPython's% timeit "волшебной функции".

Смежные вопросы