如何删除包含前一行或下一行的子字符串的行?



我有一个数据集,其中包含来自web服务的匿名搜索数据。我希望看到哪些搜索词是最常用的,但不会导致点击。然而,数据的结构方式我很难处理,所以我需要先削减它-但我能想到的唯一方法是缓慢和低效的,我对它的了解不够,无法通过搜索找到可用的答案。

我不知道数据是如何收集的,但大多数情况下,每次击键似乎都会生成一个新行-尽管有时一个单词出现在列表中,大部分或完全形成(可能是复制/粘贴?)。

一个例子:

date               , searchTerm
26-04-2022 13:30:30, d
26-04-2022 13:30:30, de
26-04-2022 13:30:31, dep
26-04-2022 13:30:31, depa
26-04-2022 13:30:31, depar
26-04-2022 13:30:32, depart
26-04-2022 13:30:32, departm
26-04-2022 13:30:33, departme
26-04-2022 13:30:34, departmen
26-04-2022 13:30:34, department
26-04-2022 13:30:34, departmen
26-04-2022 13:30:35, departme
26-04-2022 13:30:36, departm
... 
26-04-2022 13:32:11, somethi
26-04-2022 13:32:31, somethin
26-04-2022 13:32:31, something
26-04-2022 13:32:56, another word
...

在这个列表中,我想只保留说26-04-2022 13:30:34, department,26-04-2022 13:32:31, something26-04-2022 13:32:56, another word的行,但我能想到的唯一方法是遍历列表,删除包含在相邻行中的字符串行。

我相当确信这不是"正确的"。不过这是一种方法。这不是我必须经常做的事情,但如果有更好(或"正确")的方法,我宁愿学一些新的东西。

我们可以使用pandas.Series.shift来比较行与相邻行,并使用python内置运算符in来测试子字符串是否包含。

import pandas as pd
df = pd.DataFrame({'date': range(7), 'searchTerm': 'departme departmen department departmen somethin something anotherword'.split()})
print(df)
#    date   searchTerm
# 0     0     departme
# 1     1    departmen
# 2     2   department
# 3     3    departmen
# 4     4     somethin
# 5     5    something
# 6     6  anotherword
goodrows = [(x not in y and x not in z) for x, y, z in zip(df['searchTerm'], df['searchTerm'].shift(-1, fill_value=''), df['searchTerm'].shift(1, fill_value=''))]
print( df[goodrows] )
#    date   searchTerm
# 2     2   department
# 5     5    something
# 6     6  anotherword

不得不使用列表推导式有点令人沮丧。Pandas允许很多很酷的符号来操作数字,但对于字符串就不那么多了。

例如:

goodrows = not (df['searchTerm'] <= df['searchTerm'].shift(-1) or df['searchTerm'] <= df['searchTerm'].shift(1))
print( df[goodrows] )

如果searchTerm是数字,并且我们想要删除小于相邻行的行,可以工作。

但是我们不能用操作符in或方法str.contains来替换操作符<=,以使其在字符串上工作。

最新更新