Создать новый столбец панд на основе начала текстовой строки из другого столбца

У меня есть пандас dataframe с текстовым столбцом.

Я хотел бы создать новый столбец, в котором значения зависят от начала текстовой строки из текстового столбца.

Так что если 30 первых символов текстового столбца:

== 'xxx... xxx', затем верните значение 1 /

== 'yyy... yyy', тогда верните значение 2

== 'zzz... zzz', затем вернуть значение 3

если ничего из вышеперечисленного не вернет 0

2 ответа

Возможно использование нескольких numpy.where но если использовать больше условий apply:

Для выбора строк из стратов используйте индексацию с помощью str.

df = pd.DataFrame({'A':['xxxss','yyyee','zzzswee','sss'],
                   'B':[4,5,6,8]})

print (df)
         A  B
0    xxxss  4
1    yyyee  5
2  zzzswee  6
3      sss  8
#check first 3 values
a = df.A.str[:3]
df['new'] = np.where(a == 'xxx', 1, 
            np.where(a == 'yyy', 2, 
            np.where(a == 'zzz', 3, 0)))

print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0
def f(x):
    #print (x)
    if x == 'xxx':
        return 1
    elif x == 'yyy':
        return 2
    elif x == 'zzz':
        return 3
    else:
        return 0

df['new'] = df.A.str[:3].apply(f)
print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0

РЕДАКТИРОВАТЬ:

Если длина отличается, нужно только:

df['new'] = np.where(df.A.str[:3] == 'xxx', 1, 
            np.where(df.A.str[:2] == 'yy', 2, 
            np.where(df.A.str[:1] == 'z', 3, 0)))

print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0

EDIT1:

Спасибо за идею использовать Quickbeam2k1 str.startswith для проверки запуска каждой строки:

df['new'] = np.where(df.A.str.startswith('xxx'), 1, 
            np.where(df.A.str.startswith('yy'), 2, 
            np.where(df.A.str.startswith('z'), 3, 0)))

print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0

Другое и более медленное решение: однако преимущество заключается в том, что сопоставление с шаблонами является параметром функции (с неявным значением по умолчанию 0)

def map_starts_with(pat_map):
    def map_string(t):
        pats = [pat for pat in pat_map.keys() if t.startswith(pat)]
        return pat_map.get(pats[0]) if len(pats) > 0 else 0 
# get only value of "first" pattern if at least one pattern is found
    return map_string

df = pd.DataFrame({'col':[ 'xx', 'aaaaaa', 'c']})
      col
0      xx
1  aaaaaa
2       c

mapping = { 'aaa':4 ,'c':3}
df.col.apply(lambda x: map_starts_with(mapping)(x))

0    0
1    4
2    3

Обратите внимание, что мы также использовали карри здесь. Мне интересно, если этот подход может быть реализован с использованием дополнительных панд или numpy функциональности.

Обратите внимание, что "первое" сопоставление с образцом может зависеть от порядка обхода клавиш dict. Это бесполезно, если в клавишах нет совпадений. (Решение Джезраэля или его прямое обобщение также выберет один элемент для матча, но более предсказуемым образом)

Другие вопросы по тегам