创作背景
- 最近本菜鸡在帮别人处理数据,有个需求是
将一个 DataFrame 中在另一个 DataFrame 中的数据除去
- 也就是有两个 DataFrame,A 和 B,B 是 A 与另一个 DataFrame C 取交集的结果,要把 B 中的数据从 A 中删除,有指定的列 columns(有多个,不止一两个)
问题分析
这个问题的难点在于:
1. B 的列数和 A 不一样
2. 遍历 A 中每一行数据
3. 判断 A 中的一行数据是否在 B 中
问题解决
- 第一个好解决,以
columns
代替指定的列,就直接
# 只取指定的列的数据
B = B[columns]
- 其实到后边第一个问题也不是问题,也不需要这样
- 先开始我的想法是用
apply
函数遍历每一行,然后再判断- 首先是
apply
函数,如果直接对A
进行apply
的话,每个apply
获得的参数是A
的每一列数据,而不是每一行,所以我决定遍历A
的index
,代码如下:
def remove_data(index): print(index, A.loc[[index]]) # index 是个 Int64Index 对象,没有 apply # 所以先将它转化为 Series pd.Series(A.index).apply(remove_data)
- 但我刚刚百度才发现可以指定
axis
为1
就是遍历每一行,那修改后的代码如下:
def remove_data(data): # data 是一个 Series 对象 # 这里要将它转 DataFrame 并转置,方便后边处理 data = data.to_frame().T print(data) A.apply(remove_data, axis=1)
- 可我刚刚又想到了另一种方式,用
iterrows()
,没错,就是敲下这句话的时候,然后我就去实验了一下,结果可行,代码如下:
for index, item in A.iterrows(): # 和 2 中的 data 一样,都是每行的 Series item = item.to_frame().T print(item)
- 首先是
- 最后一步,也是最重要的一步,怎么判断这一行数据是否在
B
中?- 我先开始想的是:
用 B[B[c1]==data1 & B[c2]==data2 ....]
,但因为指定的列很多,所以这样写起来确实麻烦,如果指定的列少还是可以使用这个方法的 - 然后我就想到了一个妙计:
- 用
merge
合并B
和每一行的 DataFrame
(上边都把 Series 转成 DataFrame 了),其中,on
就设置成指定的列 - 如果有数据,就说明这一行在
B
中,反之,则不在B
中(我真聪明) - 代码如下
- 用
- 我先开始想的是:
# 用 index
def remove_data(index):
if not pd.merge(B, A.loc[[index]], on=columns).empty:
A.drop(index, inplace=True)
pd.Series(A.index).apply(remove_data)
# 用 apply(axis=1),和上边的方法各有麻烦处
def remove_data(data):
data = data.to_frame().T
if not pd.merge(B, data, on=columns).empty:
A.drop(data.index, inplace=True)
A.apply(remove_data, axis=1)
# 用 iterrows
for index, item in A.iterrows():
item = item.to_frame().T
if not pd.merge(B, item, on=columns).empty:
A.drop(index, inplace=True)
- 成功完成任务!!!
结尾
以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。