我有两个数据帧:一个(A
)具有一些regex格式的白名单主机名(即(.*)microsoft.com
,(*.)go.microsoft.com
…)和另一个(B
)具有站点的实际完整主机名。我想用白名单(第一个)数据帧的regex文本向第二个数据帧添加一个新列。然而,Pandas的.replace()
方法似乎并不关心其to_replace
和value
参数的顺序。在
我的数据如下:
In [1] A
Out[1]:
wildcards \
42 (.*)activation.playready.microsoft.com
35 (.*)v10.vortex-win.data.microsoft.com
40 (.*)settings-win.data.microsoft.com
43 (.*)smartscreen.microsoft.com
39 (.*).playready.microsoft.com
38 (.*)go.microsoft.com
240 (.*)i.microsoft.com
238 (.*)microsoft.com
regex
42 re.compile('^(.*)activation.playready.microsof...
35 re.compile('^(.*)v10.vortex-win.data.microsoft...
40 re.compile('^(.*)settings-win.data.microsoft.c...
43 re.compile('^(.*)smartscreen.microsoft.com$')
39 re.compile('^(.*).playready.microsoft.com$')
38 re.compile('^(.*)go.microsoft.com$')
240 re.compile('^(.*)i.microsoft.com$')
238 re.compile('^(.*)microsoft.com$')
In [2] B.head()
Out[2]:
server_hostname
146 mobile.pipe.aria.microsoft.com
205 settings-win.data.microsoft.com
341 nav.smartscreen.microsoft.com
406 v10.vortex-win.data.microsoft.com
667 www.microsoft.com
请注意,A
有一列经过编译的regex,其格式与wildcards
列的格式相似。我想将wildcard
列添加到B
中,如下所示:
B.loc[:,'wildcards'] = B['server_hostname'].replace(A['regex'].tolist(), A['wildcards'].tolist())
但问题是,B
的所有通配符值都变成了(.*)microsoft.com
。无论A
通配符值的顺序如何,都会发生这种情况。似乎.replace()
的目的是首先按最短值使用to_replace
正则表达式,而不是提供的顺序。在
如何提供to_replace
值的列表,以便最终获得与B
值关联的最详细的主机名wildcards
值?在
下面是一种使用双列表理解和
re.sub()
函数来完成此操作的方法:^{pr2}$
大多数答案使用
apply()
,这比内置的向量函数解要慢。我希望使用.replace()
,因为它是一个内置的向量函数,所以它会很快。@vlemaistre的答案是唯一一个不使用.apply()
的方法,我的解决方案不是将每个通配符编译成regex,而是将其视为使用逻辑的右手子串:“如果server_hostname
以wildcard
结尾,那么它就是匹配的”。只要我按长度对通配符进行排序,它就可以正常工作。在我的功能是:
这里,
accepts_df
与之前的B
相似,whitelist_df
与之前的A
相似,但有两个区别:regex
列wildcards
值不再是glob/regex格式(即“(.*)微软.com“变成”微软.com““为了在我的机器上对答案进行基准测试,我将使用我的作为基线,用27秒的时间处理100k
accepts_df
行和400whitelist_df
行。使用同一个数据集,下面是其他解决方案的时间(我很懒:如果它们没有跑出大门,我就没有调试太多东西来发现):A
排序,则为最佳匹配):超过6分钟,因此退出。。。在lastgroup
:没有测试,因为我不能(快速)构建一个长的重新编程。在Series.str.match()
:错误:“pandas.core.索引.base.invalidIndex错误:仅对值唯一的索引对象重新编制索引”最终,我们的答案中没有一个能说明如何按需要使用
.replace()
,所以暂时,我将这个问题留待几个星期,以防有人能提供更好地使用.replace()
的答案,或者至少是其他一些基于向量的快速解决方案。在那之前,我会保留我所拥有的,或者在我验证结果后使用aws_学徒的。在编辑 我改进了匹配器,在两个DFs中添加了一个“domain”列,它由每个通配符/服务器主机名(即微软网站变成“微软.com"). 然后,我在两个DF上使用
groupby('domain')
,遍历域的白名单组,从服务器主机名DF(B)获取同一个域组,并使用每个组中通配符/服务器主机名的子集进行匹配。这把我的处理时间缩短了一半。在另一种方法是使用SequenceMatcher和{a2}。在
从@vlemaistre给出的答案中获取数据
相关问题 更多 >
编程相关推荐