Pandas:当一列匹配关键字,另一列包含值时,有条件地删除行



我有下面的DataFrame和Dict.它不需要是字典,但键值对属于一起。

现在的问题是,我想删除"company"与"removal_dict"键匹配的行。作为同一行的第二个条件,"astring"中的值必须包含该特定键的值字符串该值不必是1:1匹配,只需包含该字符串即可

df = pd.DataFrame({'ID': ['A', 'B', 'C', 'D', 'E', 'F'], 
'company': ['BRAMSUNG', 'BRAMSUNG', 'VRENOVO', 'WRAPPLE', 'PIRCOSOFT', 'PIRCOSOFT'],
'astring': ['BRAMSUNG MAINSTREET SEOUL', 'BRAMSUNG SUBSTREET SEOUL', 'LOOKING FOR VRENOVO IN BRAMSUNG MAINSTREET', 'I GO FOR WRAPPLE IN BRAMSUNG MAINSTREET', 'PIRCOSOFT ACCOUNT NR. 1222', 'DEPOSIT TO PIRCOSOFT ACCOUNT NOW']
})
removal_dict = {'BRAMSUNG': 'BRAMSUNG MAINSTREET',
'PIRCOSOFT': 'PIRCOSOFT ACCOUNT NR.',
'VRENOVO': 'LOOKING FOR VRENOVO'
}
>>> df

ID  company    astring             
0   A   BRAMSUNG   BRAMSUNG MAINSTREET SEOUL
1   B   BRAMSUNG   BRAMSUNG SUBSTREET SEOUL
2   C   VRENOVO    LOOKING FOR VRENOVO IN BRAMSUNG MAINSTREET
3   D   WRAPPLE    I GO FOR WRAPPLE IN BRAMSUNG MAINSTREET
4   E   PIRCOSOFT  PIRCOSOFT ACCOUNT NR. 1222
5   F   PIRCOSOFT  DEPOSIT TO PIRCOSOFT ACCOUNT NOW

因此,ID的A、C和E应该被丢弃。

示例:必须删除ID A,因为removal_dict中有一个键BRAMSUNG和一个值BRAMSUNG MAINSTREET。另一方面,ID B不能被丢弃,因为只有密钥匹配,但没有值。

预期结果应为:

>>> df

ID  company    astring             
1   B   BRAMSUNG   BRAMSUNG SUBSTREET SEOUL
3   D   WRAPPLE    I GO FOR WRAPPLE IN BRAMSUNG MAINSTREET
5   F   PIRCOSOFT  DEPOSIT TO PIRCOSOFT ACCOUNT NOW

创建一个包含所有字符串开始可能性的数据帧:

temp_df = df['astring'].to_frame() 
.merge(pd.Series(removal_dict.values(), name='contains'), how='cross')

然后创建一个数据帧,其中包含与删除规则匹配的条目。

removals = temp_df[
temp_df.apply(lambda r: r['astring'].startswith(r['contains']), axis=1)]

我想不出一种明显的方法来避免str.startswithapply循环。使用pd.Series.str.startswith没有帮助,因为它是针对单个字符串应用的,而不是针对两列字符串按元素应用。

无论如何,只是子集:

>>> df[~df['astring'].isin(removals['astring'])]
ID    company                                  astring
1  B   BRAMSUNG                 BRAMSUNG SUBSTREET SEOUL
3  D    WRAPPLE  I GO FOR WRAPPLE IN BRAMSUNG MAINSTREET
5  F  PIRCOSOFT         DEPOSIT TO PIRCOSOFT ACCOUNT NOW

在我看来,在这个解决方案的某个时刻,您需要通过.apply(..., axis=1)或某些显式迭代进行显式迭代。

逐行应用解决方案

def check_removal(row, removal_dict):
"""returns True where the aligned removal string is in df["astring"]"""
removal_string = removal_dict.get(row["company"])
if removal_string is None:
return False
return removal_string in row["astring"]
mask = df.apply(check_removal, removal_dict=removal_dict, axis=1)
new_df = df.loc[~mask]
print(new_df)
ID    company                                  astring
1  B   BRAMSUNG                 BRAMSUNG SUBSTREET SEOUL
3  D    WRAPPLE  I GO FOR WRAPPLE IN BRAMSUNG MAINSTREET
5  F  PIRCOSOFT         DEPOSIT TO PIRCOSOFT ACCOUNT NOW

拆分应用组合(groupby(解决方案如果您有少量的大型集团(公司(,则此解决方案应该比逐行应用更快。

如果您有少量的唯一组,那么这种性能应该类似于逐行应用。

pieces = []
for group_name, group_data in df.groupby("company"):
# if this group is not in removal_dict, keep everything
if group_name not in removal_dict.keys():
mask = np.ones(group_data.shape[0], dtype=bool)
# if this group_name is in removal_dict, comapre w/ str.contains
else:
mask = ~group_data["astring"].str.contains(removal_dict[group_name])
matches = group_data.loc[mask]
if not matches.empty:
pieces.append(matches)
new_df = pd.concat(pieces).sort_index()
print(new_df)
ID    company                                  astring
1  B   BRAMSUNG                 BRAMSUNG SUBSTREET SEOUL
3  D    WRAPPLE  I GO FOR WRAPPLE IN BRAMSUNG MAINSTREET
5  F  PIRCOSOFT         DEPOSIT TO PIRCOSOFT ACCOUNT NOW

相关内容

  • 没有找到相关文章

最新更新