添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

0 人关注

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

现在的问题是,我想删除那些'company'与'removation_dict'的键相匹配的行。作为同一行的第二个条件,'string'中的值必须包含那个特定键的值的字符串。 该值不一定是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'
    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必须被放弃,因为有一个键荣盛集团和一个值荣盛集团 MAINSTREET在removation_dict中。另一方面,ID B不能被删除,因为只有键匹配,而没有值。

Expected result should be:

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
3 个评论
因此,这并不是真正的标签问题,而是删除重复的内容?
替换代码0】不是重复的
这不是一个重复的事情。它是关于两个放弃的行,其中1列与关键相匹配,另一列的值正好是该关键存在的(但可以有更多)。
python
pandas
Gitano
Gitano
发布于 2021-07-16
2 个回答
ifly6
ifly6
发布于 2021-07-16
0 人赞同

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

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)]

我想不出有什么明显的方法可以避免applystr.startswith的循环。使用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
    
Cameron Riddell
Cameron Riddell
发布于 2021-07-16
0 人赞同

在我看来,你需要在这个解决方案中的某个点上进行显式迭代,要么通过 .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)解决方案 如果你有少量的大组(公司),这个解决方案should要比逐行应用快。

如果你有少量的独特组,那么这个性能should是类似于一行一列的应用。

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)