Pandas布尔索引与两个列表的比较:相同(?)方法,不同的结果

时间:2015-06-28 11:46:41

标签: python pandas

我有一个名为bom2的表(大约74k行+其他列,但我们只对Assembly和Finish产品感兴趣。为了澄清事情,两个列中都有相同的Assembly和Finish产品ID。

  bom2=pd.DataFrame({'Assembly': {0: '0138104116',
  1: '0309005994',
  2: '0309005996',
  3: '0309005998',
  4: '0309005998',
  5: '0309005998',
  6: '0309005998',
  7: '0312005996',
  8: '0312005997',
  9: '0312005998'},
 'Finish product': {0: '0138104116',
  1: '0309005994',
  2: '0309005996',
  3: '0309005998',
  4: '0309005998',
  5: '0309005998',
  6: '0309005998',
  7: '0312005996',
  8: '0312005997',
  9: '0312005998'}})

我需要:

获取所有装配ID

与完成产品ID进行比较

只接受Finish产品在Assembly列中的任何位置没有ID的行。

方法1:

nejsou = bom2[-bom2['Finish product'].isin(bom2.Assembly.tolist())] 

方法2:

ass = bom2.Assembly.tolist()
fin = bom2['Finish product'].tolist()
nee=list()  #will contain Assembly IDs which do not occur in 'Finish product'
for a in ass:
    if a not in fin: nee.append(a)

在下一步中使用ID' nee'通过

搜索相应的行
bom2[bom2.Assembly.isin(nee)]

我期待这两种方法是等价的,但是当我检查每种方法得到的汇编ID的数量时,我会得到不同的数字。

print "method(1 + 2):", len(set(nejsou.Assembly.tolist()+nee)), "Unique Assembly IDs"
print "method(1):",len(set(nejsou.Assembly.tolist())), "Unique Assembly IDs"
print "method(2):",len(set(nee)), "Unique Assembly IDs"

method(1 + 2): 4021 Unique Assembly IDs
method(1): 4015 Unique Assembly IDs
method(2): 1986 Unique Assembly IDs

似乎方法1(布尔过滤)捕获方法2 +大约2k其他人捕获的所有案例,我无法弄清楚是什么案例。

这两种方法有何不同? 还有其他方法可以达到预期的效果吗?

2 个答案:

答案 0 :(得分:1)

考虑以下玩具示例:

import numpy as np
import pandas as pd

bom2 = pd.DataFrame(
    [
        ['A', 'F'],
        ['AF', 'F'],

        ['AF2', 'F'],   
        ['A', 'AF2'], 

        ['A', 'AF'],
        ['A2', 'AF'],

    ], columns=['ASS', 'FIN'])

print(bom2)
#    ASS  FIN
# 0    A    F
# 1   AF    F
# 2  AF2    F
# 3    A  AF2
# 4    A   AF
# 5   A2   AF

"模式"是:

  • AFAF2指的是ASS和FIN中的IDS。
  • AA2仅限于ASS。
  • F仅限于FIN。

然后:

ass = bom2['ASS'].tolist()
fin = bom2['FIN'].tolist()

# filter out rows of bom2 where FIN equals AF
nejsou = bom2[-bom2['FIN'].isin(ass)] 

nee = list()  #will contain ASS not in FIN
for a in ass:
    if a not in fin: nee.append(a)

print(nejsou)
#    ASS FIN
# 0    A   F
# 1   AF   F
# 2  AF2   F

产量

print "method(1 + 2):", len(set(nejsou.ASS.tolist()+nee)), "Unique ASS IDs"
# method(1 + 2): 4 Unique ASS IDs

print "method(1):",len(set(nejsou.ASS.tolist())), "Unique ASS IDs"
# method(1): 3 Unique ASS IDs

print "method(2):",len(set(nee)), "Unique ASS IDs"
# method(2): 2 Unique ASS IDs

请注意

print(set(nee))
# set(['A', 'A2'])

print(set(nejsou.ASS.tolist()))
# set(['A', 'AF2', 'AF'])

因此,方法(1)和方法(2)产生不同的结果。 如果您遵循该模式,则可以将添加为任意数量的项目 集。

  • 要在不增加方法(2)的情况下增加方法(1),请添加更多行,例如AF

    ['AFn', 'F'],
    ['A', 'AFn'],
    
  • 要在不增加方法(1)的情况下增加方法(2),请添加更多行,例如A2

    ['An', 'AF'], 
    

仅获取Finish产品在其中的任何位置都没有ID的行 装配栏使用方法1:

In [107]: bom2.loc[~bom2['FIN'].isin(bom2['ASS'])]
Out[107]: 
   ASS FIN
0    A   F
1   AF   F
2  AF2   F

不是方法2:

In [109]: bom2[bom2['ASS'].isin(nee)]
Out[109]: 
  ASS FIN
0   A   F
4   A  AF  <-- WRONG; AF is in bom2['ASS']
5  A2  AF  <-- WRONG

答案 1 :(得分:0)

这不是关于method1和method2,因此不是关于编程技术而是关于逻辑。更有意思的是,如果在第二种方法中使用布尔索引/过滤,则会得到相同的结果,反之亦然。 这是因为,如果我们将每个列表中的一些唯一值合并,那么每个列表中将有相同的值,这些值将在set()函数之后变为一个值而不是两个值。

考虑以下示例:

a = [1,2,3]
b = [3,4,5]

print set(a)
print set(b)
print
print len(set(a))
print len(set(b))
print
print set(a+b)
print
print len(set(a+b))

输出:

set([1, 2, 3])
set([3, 4, 5])

3
3

set([1, 2, 3, 4, 5])

5

很高兴得到帮助!如果您觉得它对您有用,请随时接受我的回答。 : - )