根据另一列是否包含列表中的名称,在Pandas中设置一列



我已经为这个问题挣扎了一段时间,所以我觉得是时候问了。

我有一份名单:

names = ["john", "sally", "tom"]

我有一个df,其中一列是actionaction有很多不同的东西,例如:

  • "和汤姆一起去散步
  • "带莎莉去商店">

我想创建一个名为partner的新列,并将其设置为action中的名称。我已经有了列集,它已经为一些日志填充了,但不是全部。

我试过了:

for name in names:
df['partner'] =  np.where(df.action.str.contains(name), name, df['partner'] )

但我得到了这个错误:

类型错误:第一个参数必须是字符串或编译模式

我这样做对吗?有更好的方法吗?如有任何帮助,我们将不胜感激。

编辑:要制作我的df样本,你可以使用:

names = ["john", "sally", "tom"]
d = {'name': ['mark','rick','mark','jon', 'lenny'], 'action': ['Went for a walk with tom', 'Took sally to the store', 'Went for a walk with john', 'Went racing with tom and lost', 'Took john to the store'],
'partner': ['tom', '', 'john', '', 'john']}
df = pd.DataFrame(data=d)
df

列表"names"包含了字符串中所有可能的名称,所以我认为最简单的方法是找到字符串中的名称,并将其设置为partners列。

这是我得到的完整错误:


TypeError                                 Traceback (most recent call last)
<ipython-input-68-ed79b0ff06a7> in <module>()
11 
12 for partner in partners:
---> 13     EscrowLogs.loc[EscrowLogs.action.str.contains(partner), 'partner'] = partner
14 
15 
~Anaconda3libsite-packagespandascorestrings.py in contains(self, pat, case, flags, na, regex)
2415     def contains(self, pat, case=True, flags=0, na=np.nan, regex=True):
2416         result = str_contains(self._data, pat, case=case, flags=flags, na=na,
-> 2417                               regex=regex)
2418         return self._wrap_result(result)
2419 
~Anaconda3libsite-packagespandascorestrings.py in str_contains(arr, pat, case, flags, na, regex)
385             flags |= re.IGNORECASE
386 
--> 387         regex = re.compile(pat, flags=flags)
388 
389         if regex.groups > 0:
~Anaconda3libre.py in compile(pattern, flags)
232 def compile(pattern, flags=0):
233     "Compile a regular expression pattern, returning a Pattern object."
--> 234     return _compile(pattern, flags)
235 
236 def purge():
~Anaconda3libre.py in _compile(pattern, flags)
283         return pattern
284     if not sre_compile.isstring(pattern):
--> 285         raise TypeError("first argument must be string or compiled pattern")
286     p = sre_compile.compile(pattern, flags)
287     if not (flags & DEBUG):
TypeError: first argument must be string or compiled pattern

我需要一个可验证的数据样本来确定,但使用布尔索引应该有效:

for name in names:
df.loc[df.action.str.contains(name), 'partner'] = name

根据我的评论,您可以编写一个函数来迭代数据帧的行,并捕获产生错误/异常的值。

例如,如果操作字段无法解析,则可以使用此函数返回null值:

names = ["john", "sally", "tom"]
def get_partner(p, a):
# if row already contains partner value, leave as is
if p:
return p
# otherwise, extract partner name from the action column
else:
try:
for name in names:
if name in a:
return name
# for any problematic action strings, return null value
# (can be replaced with some other string that you can later check)
except:
return None

您也可以使用这个不需要在名称上循环的函数。它将每个句子拆分为单词列表,并删除名称列表中未找到的所有单词,只留下名称值。如果有多个名称,则使用逗号分隔符将它们分隔开。

names = ["john", "sally", "tom"]
def get_partner(p, a):
# if row already contains partner value, leave as is
if p:
return p
# otherwise, extract partner name(s) from the action column
else:
try:
return ",".join([i for i in a.split() if i in names])
# for any problematic action strings, return null value
# (can be replaced with some other string that you can later check)
except:
return None

然后,您将使用.apply()在数据帧上运行函数:

df['partner'] = df.apply(lambda x: get_partner(x['partner'], x['action']), axis=1)

最新更新