Python 根据另一列是否包含列表中的名称在列表中设置列
我已经为这个问题挣扎了一段时间,所以我想是时候问一下了 我有一份名单:Python 根据另一列是否包含列表中的名称在列表中设置列,python,pandas,Python,Pandas,我已经为这个问题挣扎了一段时间,所以我想是时候问一下了 我有一份名单: names = ["john", "sally", "tom"] 我有一个df,其中一列是action。 操作有许多不同的功能,例如: “和汤姆去散步” “带萨莉去商店” 我想创建一个名为partner的新列,并将其设置为action中的名称。 我已经设置了这个列,它已经填充了一些日志,但不是所有日志 我试过: for name in names:
names = ["john", "sally", "tom"]
我有一个df,其中一列是action
。
操作
有许多不同的功能,例如:
- “和汤姆去散步”
- “带萨莉去商店”
partner
的新列,并将其设置为action
中的名称。
我已经设置了这个列,它已经填充了一些日志,但不是所有日志
我试过:
for name in names:
df['partner'] = np.where(df.action.str.contains(name), name, df['partner'] )
但我得到了这个错误:
TypeError:第一个参数必须是字符串或编译模式
我这样做对吗?有更好的方法吗?任何帮助都将不胜感激
编辑:要制作我的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回溯(最近一次调用)
在()
11
12对于合作伙伴中的合作伙伴:
--->13 EscrowLogs.loc[EscrowLogs.action.str.contains(partner),'partner']=partner
14
15
包含中的~\Anaconda3\lib\site packages\pandas\core\strings.py(self、pat、case、flags、na、regex)
2415 def包含(self、pat、case=True、flags=0、na=np.nan、regex=True):
2416 result=str\u包含(self.\u数据,pat,case=case,flags=flags,na=na,
->2417正则表达式=正则表达式)
2418返回自包装结果(结果)
2419
str_中的~\Anaconda3\lib\site packages\pandas\core\strings.py包含(arr、pat、case、flags、na、regex)
385标志|=重新忽略案例
386
-->387 regex=re.compile(pat,flags=flags)
388
389如果regex.groups>0:
编译中的~\Anaconda3\lib\re.py(模式、标志)
232 def编译(模式,标志=0):
233“编译正则表达式模式,返回模式对象。”
-->234返回编译(模式、标志)
235
236 def清除():
编译中的~\Anaconda3\lib\re.py(模式、标志)
283返回模式
284如果不是sre_compile.isstring(模式):
-->285 raise TypeError(“第一个参数必须是字符串或编译模式”)
286 p=sre_compile.compile(模式、标志)
287如果不是(标志和调试):
TypeError:第一个参数必须是字符串或编译模式
我需要一个可验证的数据样本来确定,但使用布尔索引应该可以:
for name in names:
df.loc[df.action.str.contains(name), 'partner'] = name
在我的评论之后,您可以编写一个函数来迭代数据帧的行,并捕获产生错误/异常的值 例如,如果无法解析操作字段,可以使用此函数返回空值:
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)
能否添加格式化为数据帧的数据样本?谢谢。
.str.contains
方法不是矢量化的,因此您需要仔细考虑此处的迭代,尽管我不愿意这么说;这可能是apply
和一些正则表达式根据dict获得匹配的一个例子。我不是那种把它作为答案的人。但是,为了公平起见,您至少只需要通过df行一次,这取决于数据的大小。我的直觉是,它可能相当小,而应用正则表达式则是过火了。@k_n_c如果你的直觉是错误的,我已经可以看到时间复杂性在这个问题上爆炸了。把句子分解不容易,我怀疑它涉及到许多不同的方法。我在这方面也犯了同样的错误。我将尝试使用我的df样本进行更新。
df['partner'] = df.apply(lambda x: get_partner(x['partner'], x['action']), axis=1)