使用Pandas

时间:2016-10-11 04:53:30

标签: python pandas group-by boolean closest

我有一个包含类别和值的数据框。我需要找到最接近值的每个类别中的值。我认为我很接近,但在将argsort的结果应用到原始数据帧时,我无法获得正确的输出。

例如,如果输入是在下面的代码中定义的,则输出应该只有(a, 1, True)(b, 2, True)(c, 2, True),而所有其他isClosest Values都应该为False。

如果多个值最接近,那么它应该是标记的第一个值。

以下是我的代码,但我无法正确地重新应用于数据框。我会喜欢一些指示。

df = pd.DataFrame()
df['category'] = ['a', 'b', 'b', 'b', 'c', 'a', 'b', 'c', 'c', 'a']
df['values'] = [1, 2, 3, 4, 5, 4, 3, 2, 1, 0]
df['isClosest'] = False

uniqueCategories = df['category'].unique()
for c in uniqueCategories:
    filteredCategories = df[df['category']==c]    
    sortargs = (filteredCategories['value']-2.0).abs().argsort()
    #how to use sortargs so that we set column in df isClosest=True if its the closest value in each category to 2.0?

2 个答案:

答案 0 :(得分:6)

您可以创建绝对差异列:

df['dif'] = (df['values'] - 2).abs()

df
Out: 
  category  values  dif
0        a       1    1
1        b       2    0
2        b       3    1
3        b       4    2
4        c       5    3
5        a       4    2
6        b       3    1
7        c       2    0
8        c       1    1
9        a       0    2

然后使用groupby.transform检查每组的最小值是否等于您计算的差异:

df['is_closest'] = df.groupby('category')['dif'].transform('min') == df['dif']

df
Out: 
  category  values  dif is_closest
0        a       1    1       True
1        b       2    0       True
2        b       3    1      False
3        b       4    2      False
4        c       5    3      False
5        a       4    2      False
6        b       3    1      False
7        c       2    0       True
8        c       1    1      False
9        a       0    2      False

df.groupby('category')['dif'].idxmin()还会为您提供每个类别最接近的值的索引。您也可以使用它进行映射。

供选择:

df.loc[df.groupby('category')['dif'].idxmin()]
Out: 
  category  values  dif
0        a       1    1
1        b       2    0
7        c       2    0

对于作业:

df['is_closest'] = False
df.loc[df.groupby('category')['dif'].idxmin(), 'is_closest'] = True
df
Out: 
  category  values  dif is_closest
0        a       1    1       True
1        b       2    0       True
2        b       3    1      False
3        b       4    2      False
4        c       5    3      False
5        a       4    2      False
6        b       3    1      False
7        c       2    0       True
8        c       1    1      False
9        a       0    2      False

这些方法之间的区别在于,如果您根据差异检查相等性,则在关联的情况下,对于所有行,您将获得True。但是,对于idxmin,它将在第一次出现时返回True(每个组只返回一个)。

答案 1 :(得分:3)

使用DataFrameGroupBy.idxmin的解决方案 - 获取每组最小值的索引,然后将Index.isin的布尔掩码分配给列isClosest

idx = (df['values'] - 2).abs().groupby([df['category']]).idxmin()
print (idx)
category
a    0
b    1
c    7
Name: values, dtype: int64

df['isClosest'] = df.index.isin(idx)
print (df)
  category  values isClosest
0        a       1      True
1        b       2      True
2        b       3     False
3        b       4     False
4        c       5     False
5        a       4     False
6        b       3     False
7        c       2      True
8        c       1     False
9        a       0     False