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

2024-10-01 15:43:20 发布

您现在位置:Python中文网/ 问答频道 /正文

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

现在的问题是,我想删除“company”与“removation\u 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,因为在删除指令中有一个键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

Tags: iniddfforaccountcompanylookingastring
2条回答

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

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

拆分应用组合(分组方式)解决方案 如果您有少数大型集团(公司),此解决方案比按行应用更快

如果您有少量的唯一组,则此性能类似于行应用

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

相关问题 更多 >

    热门问题