Заменить значения в серии панд из списка кортежей - PullRequest
0 голосов
/ 01 ноября 2019

Проблема: хотите заменить значения в ряду панд значением в списке кортежей, где конкретное значение ряда должно начинаться с первого значения кортежа. Ниже приведен пример:

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])

Есть лилучший способ сделать это, не теряя преимущества векторизации?

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Не уверен, что это быстрее, но это альтернатива:

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
0 голосов
/ 01 ноября 2019

После долгих усилий и исследований в интернете, мы узнали, что np.select - лучший путь и векторизация. Ниже приведено решение, которое выигрывает в случае, когда серия (а) достаточно велика. Ниже приведено решение:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...