2017-10-13 64 views
1

考虑以下两个data.frames在Python 3使用大熊猫创建:删除在在python另一个data.frame确切的行和一个data.frame的行频率3

a1 = pd.DataFrame(({'A': [1, 2, 3, 4, 5, 2, 4, 2], 'B': ['a', 'b', 'c', 'd', 'e', 'b', 'd', 'b']})) 
a2 = pd.DataFrame(({'A': [1, 2, 3, 2], 'B': ['a', 'b', 'c', 'b']})) 

我想删除在A2 A1的确切行,这样的结果应该是:

A B 
4 d 
5 e 
4 d 
2 b 

注意,一排在A1 2 b为保留在最终结果(实际上只有其中的一个被与一个取消在a2)中。有没有在熊猫或任何其他库中的任何内置函数来获得这个结果?

+0

这个术语是但不幸的是'pd.Index.difference()'不足以应付,尽管它意味着集合差异。我希望能使用像'pd.Index(a1).difference(a2)'这样的东西,但它不能正确处理非唯一的项目。 –

+0

约翰Zwinck我今天了解到'索引(a1)'。希望我完成了你的方法 – Dark

回答

1

允许使用GROUPBY cumcount:

a1['count'] = a1.groupby(['A','B']).cumcount() 
a2['count'] = a2.groupby(['A','B']).cumcount() 

选项1 - 合并和查询选项2

df = (pd.merge(a1,a2, indicator=True, how='left') 
     .query("_merge != 'both'") 
     .drop(['_merge','count'], 1)) 

- 随着折射率差合并即

i = a1.index.difference(a1.merge(a2,on=['A','B','count']).index) 
df = a1.loc[i].drop('count',1) 
0后

选项3 - 完成@约翰Zwinck的做法

df =pd.DataFrame(pd.Index(a1).difference(pd.Index(a2)).tolist(),columns=a2.columns).drop(['count'],1) 

输出: “差集”

 
    A B 
3 4 d 
4 5 e 
6 4 d 
7 2 b 
+1

棒极了!它确实给我想要的东西。 – RBL

+0

@RBL做投票,不要忘记接受答案。 – Dark

1

使用的list的定义和remove

l1=a1.values.tolist() 
l2=a2.values.tolist() 
for x in l2: 
    l1.remove(x) 

pd.DataFrame(l1,columns=a1.columns) 

Out[173]: 
    A B 
0 4 d 
1 5 e 
2 4 d 
3 2 b 

时间


巴拉斯的 1日。

start_time = timeit.default_timer() 
a1['count'] = a1.groupby(['A','B']).cumcount() 
a2['count'] = a2.groupby(['A','B']).cumcount() 
df = (pd.merge(a1,a2, indicator=True, how='left') 
     .query("_merge != 'both'") 
     .drop(['_merge','count'], 1)) 
print(timeit.default_timer() - start_time) 
0.012827654755454887 

2nd。

start_time = timeit.default_timer() 
a1['count'] = a1.groupby(['A','B']).cumcount() 
a2['count'] = a2.groupby(['A','B']).cumcount() 
i = a1.index.difference(a1.merge(a2,on=['A','B','count']).index) 
df = a1.loc[i].drop('count',1) 
print(timeit.default_timer() - start_time) 
0.05914717068662867 

3rd。

start_time = timeit.default_timer() 
a1['count'] = a1.groupby(['A','B']).cumcount() 
a2['count'] = a2.groupby(['A','B']).cumcount() 
df =pd.DataFrame(pd.Index(a1).difference(pd.Index(a2)).tolist(),columns=a2.columns).drop(['count'],1) 
print(timeit.default_timer() - start_time) 
0.006586597486375467 

矿:

start_time = timeit.default_timer() 
l1=a1.values.tolist() 
l2=a2.values.tolist() 
for x in l2: 
    l1.remove(x) 
pd.DataFrame(l1,columns=a1.columns) 
print(timeit.default_timer() - start_time) 
0.0028012795203835594 

数据输入样本的100倍。

a1=pd.concat([a1]*100,axis=0) 
a2=pd.concat([a2]*100,axis=0) 
+0

是的,它确实给出了我正在寻找的结果,但有没有办法避免循环,因为我的data.frames包含数千和数千行以及大约10列。 – RBL

+2

这样一个不错的downvote你能给我理由吗? – Wen

+1

它是一个很好的解决方案,不知道为什么downvote。我upvoted。 – Dark

相关问题