Создать новый столбец панд на основе начала текстовой строки из другого столбца
У меня есть пандас 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. Это бесполезно, если в клавишах нет совпадений. (Решение Джезраэля или его прямое обобщение также выберет один элемент для матча, но более предсказуемым образом)