我的数据框中有一个包含字符串数据的列。我需要创建一个新的整数列,每个唯一的字符串一个。我将使用此列作为多索引的第二级。下面的代码可以解决问题,但我想知道Pandas中是否有更高效的解决方案呢?
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
答案 0 :(得分:4)
for i,e in enumerate(df.c2.unique()):
df.loc[df.c2 == e,'c3'] = i
可以替换为
df['c3'] = pd.Categorical(df['c2']).codes
即使对于这个小型DataFrame,使用Categorical也是(大约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)})
然后使用Categorical(约56倍)更快:
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"魔术功能"。