[英]Pandas: Extract rows of a DF when a column value matches with a column value of another DF
[英]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.startswith
的apply
循環。 使用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.