我有一个如下所示的列表:li = ['ShortHair','LongHair','Medium Hair']
我想检查col2是否包含上述任何子字符串,如果它确实从col2获取并更新col3。如果没有,那么保持col3不变。
col1 col2 col3
0 w I have ShortHair U
1 x LongHair You Have V
2 y I have no hair W
3 z Look Medium Hair! L
得到:
col1 col2 col3
0 w I have ShortHair
1 x You Have LongHair
2 y I have no hair W
3 z Look ! Medium Hair
编辑:如果数组中出现多个子字符串,请删除格式col2并使用第一个值更新col3。
我可以从col2中删除子字符串,但是我无法更新col3。我试过了:
data[data.col2.str.contains('|'.join(li)),"col3"] = data["col2"].map(lambda x: re.findall('|'.join(li),x)[0])
它会出现IndexError: list index out of range
错误。
我怎样才能做到最好?
答案 0 :(得分:1)
创建示例数据框:
df = pd.DataFrame(
{'col1': ['w', 'x', 'y', 'z'],
'col2': ['I have ShortHair', 'LongHair You Have', 'I have no hair', 'Look Medium Hair!'],
'col3': ['U', 'V', 'W', 'L']})
使用带有列表推导的lambda表达式来查找每行上的所有匹配单词。这是一个临时列,稍后将删除。
df['matches'] = df.col2.apply(lambda sentence: [word for word in li if word in sentence])
创建包含匹配单词的行的掩码。
mask = df.matches.apply(len) > 0
使用掩码和.loc
,使用第一个匹配的单词更新col3
。
df.loc[mask, 'col3'] = df.loc[mask, 'matches'].str[0]
将lambda表达式与reduce
一起使用,以从col2
中删除每个匹配的字词:
df.loc[mask, 'col2'] = (
df.loc[mask, 'col2'].apply(lambda sentence:
reduce(lambda remaining_sentence, word:
remaining_sentence.replace(word, ''), li, sentence)))
删除匹配单词的临时列。
del df['matches']
确认结果。
>>> df
col1 col2 col3
0 w I have ShortHair
1 x You Have LongHair
2 y I have no hair W
3 z Look ! Medium Hair