簡體   English   中英

Pandas:當 1 列匹配鍵且另一列包含值時有條件地刪除行

[英]Pandas: Drop rows conditionally when 1 column matches key and another column contains value

我有下面的 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

split-apply-combine (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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM