从元组列表中替换 pandas 系列中的值

Replace values in a pandas series from list of tuples

问题:想要用元组列表中的值替换 pandas 系列中的值,其中特定系列值应从元组的第一个值开始。下面是一个例子:

a = pd.Series(['New Delhi', 'Old Bombay', None, 'Banaras'])

b = [('New','Old'), ('Old','New'),('Banaras','Varanasi'), ('abc','xyz')]

Required Output :
0         Old
1         New
2        None
3    Varanasi
dtype: object

我在下面尝试过,它的效果很好,但是由于应用失去了矢量化的好处,因此速度很慢。

def test(x):
    if x is not None:
        for i in b:
            if x.startswith(i[0]):
                return i[1]
        return x
    return x


a.apply(test)

I tried list comprehension that also works but is still slow. 

pd.Series([test(x) for x in a])

有没有更好的方法在不失去矢量化优势的情况下实现这一点?

不确定这是否更快,但这是替代方案:

a.str.partition(' ').iloc[:,0].replace(*zip(*b))

结果:

0         Old
1         New
2        None
3    Varanasi
Name: 0, dtype: object


更新包含空格的起始值:

to_replace,value = zip(*b)
to_replace = [f'^{x}.*$' for x in to_replace]
a.replace(to_replace, value, regex=True)

示例:

a = pd.Series(['New Delhi', 'Old Bombay', None, 'Banaras', 'Greater city'])
b = [('New','Old'), ('Old','New'),('Banaras','Varanasi'), ('abc','xyz'), ('Greater city', 'Great' )]

结果:

0         Old
1         New
2        None
3    Varanasi
4       Great
dtype: object

在互联网上进行了大量的努力和研究之后,了解到 np.select 是更好的方法并且是矢量化的。以下是在系列 (a) 足够大的情况下表现出色的解决方案。以下是解决方案:

a = pd.Series(np.random.choice(['New Delhi', 'Old Bombay', None, 'Banaras'], replace=True, size=1000000))

case = [a.str.upper().str.startswith(i[0], na=False) for i in b]

replace = [i[1] for i in b]

%timeit -n10 -r10 pd.Series(np.select(case, replace, default=a))
10 loops, best of 10: 75.3 ms per loop