我有下面的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
拆分应用组合(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