根据列的范围和组合获取结果

时间:2019-03-18 10:14:47

标签: python pandas

样本DF:

ID   Name        Price     Sum       
1    Apple         10      180        
2    Apple         10      100        
3    Apple         10      80         
4    Orange        12      180        
5    Orange        12      190         
6    Banana        15      50       
7    Banana        15      30   

预期DF:

ID   Name        Price     Sum     Result  
1    Apple         10      180      Full Match       
2    Orange        12      180      Match - High Confidence  
3    Orange        12      190      Match - High Confidence   
4    Banana        15      50       Match - Low Confidence
5    Banana        15      30       Match - Low Confidence

问题陈述:

我需要一个Result列,它可以在以下条件下工作:

  1. 使用NamePrice组,即如果最高值不是 Apple 和Price 10 与其他人进行strong> +-30范围,然后保留结果列为Full Match的最高值行,并删除其他人(样本Df-ID 1,2,3,预期DF仅是ID 1)

  2. NamePrice组中,如果它们在 +-30范围内,并且也大于100,则结果列将为Match - High Confidence并且没有行被删除(示例Df-ID 4,5,预期DF为ID 2,3)

  3. NamePrice组中(如果它在 +-30范围内)并且小于60,则结果列将为Match - Low Confidence和没有行被删除(示例Df-ID 6,7,预期DF为ID 4,5)

当涉及的组加上范围的组合时,我无法找到任何解决方法。有帮助吗?

2 个答案:

答案 0 :(得分:1)

这是我想出的,您可以尝试一下:

#get absolute difference from max value
df['diff_abs']=abs(df.Sum-df.groupby(['Name','Price'])['Sum'].transform('max')) 
#check if diff less than 30 remove them
m=df.loc[df.duplicated(['Name','Price'],keep=False)&df.diff_abs.lt(30)].reset_index()
print(m)

   index  ID    Name  Price  Sum  diff_abs
0      0   1   Apple     10  180         0
1      3   4  Orange     12  180        10
2      4   5  Orange     12  190         0
3      5   6  Banana     15   50         0
4      6   7  Banana     15   30        20

c1=~m.duplicated(['Name','Price'],keep=False) #check if entry is just 1 and no dups
c2=m.duplicated(['Name','Price'],keep=False)&m.Sum.lt(60) #if dups check for less than 60
m['result']=np.select([c1,c2],\
   ['Full Match','Match - Low Confidence'],'Match - High Confidence')
print(m)

   index  ID    Name  Price  Sum  diff_abs                   result
0      0   1   Apple     10  180         0               Full Match
1      3   4  Orange     12  180        10  Match - High Confidence
2      4   5  Orange     12  190         0  Match - High Confidence
3      5   6  Banana     15   50         0   Match - Low Confidence
4      6   7  Banana     15   30        20   Match - Low Confidence

答案 1 :(得分:1)

我认为您需要:

#get Series for maximal value of group
maxpergroup = df.groupby(['Name','Price'])['Sum'].transform('max')
#subtract values, get absolute values and compare by greater 30
m1 = df['Sum'].sub(maxpergroup).abs().gt(30)
#get all groups where at least one True
m11 = m1.groupby([df['Name'],df['Price']]).transform('any')
#print (m11)

#compare by another values and test if all values matching per groups
m2 = df['Sum'].gt(100)
m22 = (m2 & ~m1).groupby([df['Name'],df['Price']]).transform('all')
#print (m22)

m3 = df['Sum'].lt(60)
m33 = (m3 & ~m1).groupby([df['Name'],df['Price']]).transform('all')
#print (m33)

#create new column
masks = [m11,m22, m33]
vals = ['Full Match','Match - Low Confidence','Match - High Confidence']
df['result'] = np.select(masks, vals)

#remove unnecessary rows
df = df[~m11 | df['Sum'].eq(maxpergroup)]
print (df)
   ID    Name  Price  Sum                   result
0  1   Apple   10     180  Full Match             
3  4   Orange  12     180  Match - Low Confidence 
4  5   Orange  12     190  Match - Low Confidence 
5  6   Banana  15     50   Match - High Confidence
6  7   Banana  15     30   Match - High Confidence